summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux_builds.yml2
-rw-r--r--.github/workflows/macos_builds.yml4
-rw-r--r--.github/workflows/windows_builds.yml2
-rw-r--r--SConstruct3
-rw-r--r--core/SCsub3
-rw-r--r--core/core_bind.cpp23
-rw-r--r--core/core_bind.h4
-rw-r--r--core/doc_data.cpp4
-rw-r--r--core/doc_data.h3
-rw-r--r--core/extension/extension_api_dump.cpp3
-rw-r--r--core/input/input.h2
-rw-r--r--core/input/input_event.cpp19
-rw-r--r--core/input/input_event.h4
-rw-r--r--core/io/dir_access.cpp4
-rw-r--r--core/io/dir_access.h1
-rw-r--r--core/io/file_access.cpp5
-rw-r--r--core/io/image.cpp16
-rw-r--r--core/io/image.h1
-rw-r--r--core/io/marshalls.cpp2
-rw-r--r--core/io/xml_parser.cpp46
-rw-r--r--core/io/xml_parser.h9
-rw-r--r--core/math/expression.cpp2
-rw-r--r--core/math/octree.h1271
-rw-r--r--core/object/class_db.cpp41
-rw-r--r--core/object/class_db.h17
-rw-r--r--core/object/object.h1
-rw-r--r--core/object/script_language.h2
-rw-r--r--core/object/script_language_extension.cpp2
-rw-r--r--core/object/script_language_extension.h9
-rw-r--r--core/os/os.h1
-rw-r--r--core/string/node_path.cpp15
-rw-r--r--core/string/node_path.h2
-rw-r--r--core/string/ustring.cpp393
-rw-r--r--core/string/ustring.h7
-rw-r--r--core/templates/lru.h5
-rw-r--r--core/templates/vector.h3
-rw-r--r--core/variant/binder_common.h23
-rw-r--r--core/variant/type_info.h45
-rw-r--r--core/variant/variant_call.cpp33
-rw-r--r--doc/class.xsd37
-rw-r--r--doc/classes/AudioStreamPlayer.xml1
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml1
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml1
-rw-r--r--doc/classes/BoneMap.xml56
-rw-r--r--doc/classes/Button.xml23
-rw-r--r--doc/classes/CanvasItem.xml76
-rw-r--r--doc/classes/CodeEdit.xml3
-rw-r--r--doc/classes/ColorPicker.xml25
-rw-r--r--doc/classes/Decal.xml8
-rw-r--r--doc/classes/EditorScenePostImportPlugin.xml4
-rw-r--r--doc/classes/FileDialog.xml3
-rw-r--r--doc/classes/Font.xml287
-rw-r--r--doc/classes/FontFile.xml (renamed from doc/classes/FontData.xml)252
-rw-r--r--doc/classes/FontVariation.xml76
-rw-r--r--doc/classes/GraphNode.xml21
-rw-r--r--doc/classes/HTTPRequest.xml3
-rw-r--r--doc/classes/Image.xml7
-rw-r--r--doc/classes/ImageTexture.xml12
-rw-r--r--doc/classes/Input.xml1
-rw-r--r--doc/classes/InputEventMouseMotion.xml4
-rw-r--r--doc/classes/ItemList.xml24
-rw-r--r--doc/classes/Label.xml23
-rw-r--r--doc/classes/Label3D.xml25
-rw-r--r--doc/classes/Light3D.xml1
-rw-r--r--doc/classes/LightmapGI.xml2
-rw-r--r--doc/classes/LineEdit.xml21
-rw-r--r--doc/classes/LinkButton.xml23
-rw-r--r--doc/classes/Node3D.xml7
-rw-r--r--doc/classes/NodePath.xml6
-rw-r--r--doc/classes/PackedByteArray.xml10
-rw-r--r--doc/classes/ParticlesMaterial.xml45
-rw-r--r--doc/classes/PopupMenu.xml24
-rw-r--r--doc/classes/ProjectSettings.xml9
-rw-r--r--doc/classes/ResourceSaver.xml18
-rw-r--r--doc/classes/RichTextLabel.xml8
-rw-r--r--doc/classes/ScriptLanguageExtension.xml9
-rw-r--r--doc/classes/SkeletonProfile.xml106
-rw-r--r--doc/classes/SkeletonProfileHumanoid.xml14
-rw-r--r--doc/classes/String.xml17
-rw-r--r--doc/classes/StyleBox.xml4
-rw-r--r--doc/classes/TabBar.xml24
-rw-r--r--doc/classes/TextEdit.xml26
-rw-r--r--doc/classes/TextLine.xml9
-rw-r--r--doc/classes/TextMesh.xml25
-rw-r--r--doc/classes/TextParagraph.xml28
-rw-r--r--doc/classes/TextServer.xml38
-rw-r--r--doc/classes/TextServerExtension.xml38
-rw-r--r--doc/classes/Theme.xml11
-rw-r--r--doc/classes/Tree.xml24
-rw-r--r--doc/classes/TreeItem.xml32
-rw-r--r--doc/classes/VideoStreamPlayer.xml2
-rw-r--r--doc/classes/VoxelGI.xml1
-rw-r--r--doc/classes/XMLParser.xml2
-rwxr-xr-xdoc/tools/make_rst.py65
-rw-r--r--doc/translations/ar.po111
-rw-r--r--doc/translations/ca.po110
-rw-r--r--doc/translations/classes.pot110
-rw-r--r--doc/translations/cs.po111
-rw-r--r--doc/translations/de.po111
-rw-r--r--doc/translations/el.po111
-rw-r--r--doc/translations/es.po133
-rw-r--r--doc/translations/fa.po110
-rw-r--r--doc/translations/fi.po111
-rw-r--r--doc/translations/fil.po110
-rw-r--r--doc/translations/fr.po1073
-rw-r--r--doc/translations/gl.po110
-rw-r--r--doc/translations/hi.po110
-rw-r--r--doc/translations/hu.po110
-rw-r--r--doc/translations/id.po110
-rw-r--r--doc/translations/is.po110
-rw-r--r--doc/translations/it.po113
-rw-r--r--doc/translations/ja.po111
-rw-r--r--doc/translations/ko.po122
-rw-r--r--doc/translations/lt.po110
-rw-r--r--doc/translations/lv.po110
-rw-r--r--doc/translations/mr.po110
-rw-r--r--doc/translations/nb.po110
-rw-r--r--doc/translations/ne.po110
-rw-r--r--doc/translations/nl.po110
-rw-r--r--doc/translations/pl.po113
-rw-r--r--doc/translations/pt.po319
-rw-r--r--doc/translations/pt_BR.po111
-rw-r--r--doc/translations/ro.po110
-rw-r--r--doc/translations/ru.po222
-rw-r--r--doc/translations/sk.po110
-rw-r--r--doc/translations/sr_Cyrl.po110
-rw-r--r--doc/translations/sv.po110
-rw-r--r--doc/translations/th.po110
-rw-r--r--doc/translations/tl.po113
-rw-r--r--doc/translations/tr.po134
-rw-r--r--doc/translations/uk.po111
-rw-r--r--doc/translations/vi.po111
-rw-r--r--doc/translations/zh_CN.po443
-rw-r--r--doc/translations/zh_TW.po111
-rw-r--r--drivers/gles3/environment/fog.cpp66
-rw-r--r--drivers/gles3/environment/fog.h62
-rw-r--r--drivers/gles3/environment/gi.cpp7
-rw-r--r--drivers/gles3/environment/gi.h3
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp5
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h5
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp16
-rw-r--r--drivers/gles3/rasterizer_gles3.h9
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp51
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h13
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp569
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h266
-rw-r--r--drivers/gles3/shaders/SCsub2
-rw-r--r--drivers/gles3/storage/light_storage.cpp120
-rw-r--r--drivers/gles3/storage/light_storage.h25
-rw-r--r--drivers/gles3/storage/material_storage.cpp10
-rw-r--r--drivers/gles3/storage/material_storage.h48
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp49
-rw-r--r--drivers/gles3/storage/mesh_storage.h13
-rw-r--r--drivers/gles3/storage/texture_storage.cpp55
-rw-r--r--drivers/gles3/storage/texture_storage.h19
-rw-r--r--drivers/gles3/storage/utilities.cpp353
-rw-r--r--drivers/gles3/storage/utilities.h159
-rw-r--r--drivers/unix/dir_access_unix.cpp25
-rw-r--r--drivers/unix/dir_access_unix.h4
-rw-r--r--drivers/unix/file_access_unix.cpp4
-rw-r--r--drivers/unix/file_access_unix.h1
-rw-r--r--drivers/unix/os_unix.cpp7
-rw-r--r--drivers/vulkan/vulkan_context.cpp18
-rw-r--r--editor/animation_track_editor.cpp8
-rw-r--r--editor/code_editor.cpp96
-rw-r--r--editor/debugger/editor_performance_profiler.cpp4
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/debugger/editor_visual_profiler.cpp10
-rw-r--r--editor/debugger/script_editor_debugger.cpp9
-rw-r--r--editor/doc_tools.cpp66
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_data.cpp1
-rw-r--r--editor/editor_file_dialog.cpp4
-rw-r--r--editor/editor_fonts.cpp541
-rw-r--r--editor/editor_help.cpp151
-rw-r--r--editor/editor_help.h1
-rw-r--r--editor/editor_inspector.cpp5
-rw-r--r--editor/editor_node.cpp60
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_plugin.cpp3
-rw-r--r--editor/editor_properties.cpp22
-rw-r--r--editor/editor_resource_picker.cpp14
-rw-r--r--editor/editor_resource_preview.cpp6
-rw-r--r--editor/editor_run_native.cpp4
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/editor_spin_slider.cpp7
-rw-r--r--editor/editor_themes.cpp12
-rw-r--r--editor/find_in_files.cpp4
-rw-r--r--editor/icons/BoneMapHumanBody.svg1
-rw-r--r--editor/icons/BoneMapHumanFace.svg1
-rw-r--r--editor/icons/BoneMapHumanLeftHand.svg1
-rw-r--r--editor/icons/BoneMapHumanRightHand.svg1
-rw-r--r--editor/icons/BoneMapperHandle.svg1
-rw-r--r--editor/icons/BoneMapperHandleCircle.svg1
-rw-r--r--editor/icons/BoneMapperHandleSelected.svg1
-rw-r--r--editor/icons/Font.svg2
-rw-r--r--editor/icons/FontData.svg1
-rw-r--r--editor/icons/FontFile.svg1
-rw-r--r--editor/icons/FontVariation.svg1
-rw-r--r--editor/icons/MainMovieWriteEnabled.svg1
-rw-r--r--editor/import/dynamic_font_import_settings.cpp1014
-rw-r--r--editor/import/dynamic_font_import_settings.h90
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.cpp144
-rw-r--r--editor/import/post_import_plugin_skeleton_renamer.h46
-rw-r--r--editor/import/resource_importer_bmfont.cpp12
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp193
-rw-r--r--editor/import/resource_importer_dynamic_font.h3
-rw-r--r--editor/import/resource_importer_imagefont.cpp15
-rw-r--r--editor/import/resource_importer_scene.cpp94
-rw-r--r--editor/import/resource_importer_scene.h4
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp12
-rw-r--r--editor/import/resource_importer_wav.cpp64
-rw-r--r--editor/import/scene_import_settings.cpp46
-rw-r--r--editor/import/scene_import_settings.h1
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp2
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp16
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp34
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp35
-rw-r--r--editor/plugins/asset_library_editor_plugin.h3
-rw-r--r--editor/plugins/bit_map_editor_plugin.cpp6
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp439
-rw-r--r--editor/plugins/bone_map_editor_plugin.h176
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp114
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp11
-rw-r--r--editor/plugins/editor_preview_plugins.cpp75
-rw-r--r--editor/plugins/font_config_plugin.cpp979
-rw-r--r--editor/plugins/font_config_plugin.h261
-rw-r--r--editor/plugins/font_editor_plugin.cpp106
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp17
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp12
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp1
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp23
-rw-r--r--editor/plugins/ot_features_plugin.cpp235
-rw-r--r--editor/plugins/script_text_editor.cpp9
-rw-r--r--editor/plugins/text_control_editor_plugin.cpp660
-rw-r--r--editor/plugins/text_control_editor_plugin.h115
-rw-r--r--editor/plugins/theme_editor_plugin.cpp6
-rw-r--r--editor/plugins/theme_editor_preview.cpp2
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp6
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp17
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp5
-rw-r--r--editor/project_converter_3_to_4.cpp6
-rw-r--r--editor/project_export.cpp7
-rw-r--r--editor/project_manager.cpp7
-rw-r--r--editor/property_editor.cpp6
-rw-r--r--editor/translations/af.po115
-rw-r--r--editor/translations/ar.po136
-rw-r--r--editor/translations/az.po110
-rw-r--r--editor/translations/bg.po118
-rw-r--r--editor/translations/bn.po121
-rw-r--r--editor/translations/br.po109
-rw-r--r--editor/translations/ca.po121
-rw-r--r--editor/translations/cs.po125
-rw-r--r--editor/translations/da.po119
-rw-r--r--editor/translations/de.po138
-rw-r--r--editor/translations/editor.pot99
-rw-r--r--editor/translations/el.po125
-rw-r--r--editor/translations/en_Shaw.po109
-rw-r--r--editor/translations/eo.po115
-rw-r--r--editor/translations/es.po127
-rw-r--r--editor/translations/es_AR.po130
-rw-r--r--editor/translations/et.po119
-rw-r--r--editor/translations/eu.po112
-rw-r--r--editor/translations/fa.po119
-rw-r--r--editor/translations/fi.po130
-rw-r--r--editor/translations/fil.po108
-rw-r--r--editor/translations/fr.po163
-rw-r--r--editor/translations/ga.po111
-rw-r--r--editor/translations/gl.po123
-rw-r--r--editor/translations/he.po124
-rw-r--r--editor/translations/hi.po115
-rw-r--r--editor/translations/hr.po115
-rw-r--r--editor/translations/hu.po119
-rw-r--r--editor/translations/id.po127
-rw-r--r--editor/translations/is.po111
-rw-r--r--editor/translations/it.po201
-rw-r--r--editor/translations/ja.po126
-rw-r--r--editor/translations/ka.po115
-rw-r--r--editor/translations/km.po100
-rw-r--r--editor/translations/ko.po123
-rw-r--r--editor/translations/lt.po115
-rw-r--r--editor/translations/lv.po115
-rw-r--r--editor/translations/mk.po101
-rw-r--r--editor/translations/ml.po100
-rw-r--r--editor/translations/mr.po109
-rw-r--r--editor/translations/ms.po115
-rw-r--r--editor/translations/nb.po115
-rw-r--r--editor/translations/nl.po125
-rw-r--r--editor/translations/pl.po151
-rw-r--r--editor/translations/pr.po115
-rw-r--r--editor/translations/pt.po130
-rw-r--r--editor/translations/pt_BR.po127
-rw-r--r--editor/translations/ro.po115
-rw-r--r--editor/translations/ru.po171
-rw-r--r--editor/translations/si.po109
-rw-r--r--editor/translations/sk.po115
-rw-r--r--editor/translations/sl.po115
-rw-r--r--editor/translations/sq.po115
-rw-r--r--editor/translations/sr_Cyrl.po126
-rw-r--r--editor/translations/sr_Latn.po113
-rw-r--r--editor/translations/sv.po115
-rw-r--r--editor/translations/te.po102
-rw-r--r--editor/translations/th.po124
-rw-r--r--editor/translations/tl.po119
-rw-r--r--editor/translations/tr.po141
-rw-r--r--editor/translations/uk.po221
-rw-r--r--editor/translations/ur_PK.po115
-rw-r--r--editor/translations/vi.po115
-rw-r--r--editor/translations/zh_CN.po139
-rw-r--r--editor/translations/zh_HK.po119
-rw-r--r--editor/translations/zh_TW.po129
-rw-r--r--main/main.cpp48
-rwxr-xr-xmisc/scripts/install_vulkan_sdk_macos.sh13
-rw-r--r--modules/dds/texture_loader_dds.cpp4
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml161
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp63
-rw-r--r--modules/gdscript/gdscript_cache.cpp2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp19
-rw-r--r--modules/gdscript/gdscript_editor.cpp41
-rw-r--r--modules/gdscript/gdscript_parser.cpp89
-rw-r--r--modules/gdscript/gdscript_parser.h22
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp4
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out2
-rw-r--r--modules/gltf/gltf_document.cpp37
-rw-r--r--modules/lightmapper_rd/SCsub4
-rw-r--r--modules/mono/build_scripts/make_android_mono_config.py2
-rw-r--r--modules/mono/csharp_script.cpp39
-rw-r--r--modules/mono/csharp_script.h3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs3
-rw-r--r--modules/mono/editor/bindings_generator.cpp22
-rw-r--r--modules/mono/editor/bindings_generator.h1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs43
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs16
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs22
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs28
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs28
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj2
-rw-r--r--modules/mono/glue/nodepath_glue.cpp5
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h7
-rw-r--r--modules/mono/utils/path_utils.cpp12
-rw-r--r--modules/mono/utils/string_utils.cpp2
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.cpp2
-rw-r--r--modules/text_server_adv/SCsub24
-rw-r--r--modules/text_server_adv/gdextension_build/SConstruct24
-rw-r--r--modules/text_server_adv/text_server_adv.cpp951
-rw-r--r--modules/text_server_adv/text_server_adv.h61
-rw-r--r--modules/text_server_fb/text_server_fb.cpp343
-rw-r--r--modules/text_server_fb/text_server_fb.h40
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/visual_script/visual_script.cpp3
-rw-r--r--modules/visual_script/visual_script.h1
-rw-r--r--modules/webrtc/webrtc_peer_connection_js.cpp2
-rw-r--r--modules/webrtc/webrtc_peer_connection_js.h2
-rw-r--r--platform/android/SCsub1
-rw-r--r--platform/android/detect.py8
-rw-r--r--platform/android/dir_access_jandroid.cpp304
-rw-r--r--platform/android/dir_access_jandroid.h72
-rw-r--r--platform/android/export/export_plugin.cpp124
-rw-r--r--platform/android/export/export_plugin.h4
-rw-r--r--platform/android/export/gradle_export_util.cpp4
-rw-r--r--platform/android/export/gradle_export_util.h2
-rw-r--r--platform/android/file_access_android.cpp12
-rw-r--r--platform/android/file_access_android.h8
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp283
-rw-r--r--platform/android/file_access_filesystem_jandroid.h97
-rw-r--r--platform/android/java/app/config.gradle6
-rw-r--r--platform/android/java/editor/build.gradle3
-rw-r--r--platform/android/java/editor/src/main/AndroidManifest.xml8
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt52
-rw-r--r--platform/android/java/editor/src/main/res/values/strings.xml2
-rw-r--r--platform/android/java/lib/AndroidManifest.xml2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java22
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java96
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java17
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt114
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/directory/AssetsDirectoryAccess.kt177
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/directory/DirectoryAccessHandler.kt224
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt230
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt186
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt87
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt202
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt93
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt284
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java55
-rw-r--r--platform/android/java_godot_lib_jni.cpp15
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/os_android.cpp32
-rw-r--r--platform/android/os_android.h2
-rw-r--r--platform/iphone/detect.py4
-rw-r--r--platform/iphone/display_server_iphone.mm1
-rw-r--r--platform/iphone/export/export_plugin.cpp6
-rw-r--r--platform/iphone/godot_iphone.mm5
-rw-r--r--platform/javascript/display_server_javascript.cpp4
-rw-r--r--platform/javascript/export/export_plugin.cpp9
-rw-r--r--platform/linuxbsd/display_server_x11.cpp68
-rw-r--r--platform/linuxbsd/display_server_x11.h3
-rw-r--r--platform/linuxbsd/export/export.cpp7
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp4
-rw-r--r--platform/osx/detect.py57
-rw-r--r--platform/osx/display_server_osx.mm9
-rw-r--r--platform/osx/export/export_plugin.cpp7
-rw-r--r--platform/osx/godot_application_delegate.h1
-rw-r--r--platform/osx/godot_application_delegate.mm65
-rw-r--r--platform/osx/godot_content_view.h1
-rw-r--r--platform/osx/godot_content_view.mm9
-rw-r--r--platform/osx/godot_main_osx.mm13
-rw-r--r--platform/osx/os_osx.h6
-rw-r--r--platform/osx/os_osx.mm8
-rw-r--r--platform/uwp/export/export_plugin.cpp4
-rw-r--r--platform/windows/display_server_windows.cpp19
-rw-r--r--platform/windows/display_server_windows.h14
-rw-r--r--platform/windows/export/export.cpp7
-rw-r--r--platform/windows/godot_windows.cpp4
-rw-r--r--scene/2d/animated_sprite_2d.cpp5
-rw-r--r--scene/2d/cpu_particles_2d.cpp6
-rw-r--r--scene/2d/gpu_particles_2d.cpp3
-rw-r--r--scene/2d/tile_map.cpp1
-rw-r--r--scene/3d/bone_attachment_3d.cpp21
-rw-r--r--scene/3d/bone_attachment_3d.h6
-rw-r--r--scene/3d/cpu_particles_3d.cpp11
-rw-r--r--scene/3d/decal.cpp4
-rw-r--r--scene/3d/gpu_particles_3d.cpp2
-rw-r--r--scene/3d/label_3d.cpp126
-rw-r--r--scene/3d/label_3d.h32
-rw-r--r--scene/3d/node_3d.cpp31
-rw-r--r--scene/3d/node_3d.h6
-rw-r--r--scene/3d/sprite_3d.cpp5
-rw-r--r--scene/3d/voxel_gi.cpp3
-rw-r--r--scene/gui/button.cpp85
-rw-r--r--scene/gui/button.h9
-rw-r--r--scene/gui/code_edit.cpp79
-rw-r--r--scene/gui/code_edit.h5
-rw-r--r--scene/gui/color_mode.cpp330
-rw-r--r--scene/gui/color_mode.h143
-rw-r--r--scene/gui/color_picker.cpp505
-rw-r--r--scene/gui/color_picker.h93
-rw-r--r--scene/gui/control.cpp2
-rw-r--r--scene/gui/file_dialog.cpp85
-rw-r--r--scene/gui/file_dialog.h6
-rw-r--r--scene/gui/graph_node.cpp72
-rw-r--r--scene/gui/graph_node.h5
-rw-r--r--scene/gui/item_list.cpp35
-rw-r--r--scene/gui/item_list.h5
-rw-r--r--scene/gui/label.cpp108
-rw-r--r--scene/gui/label.h9
-rw-r--r--scene/gui/line_edit.cpp136
-rw-r--r--scene/gui/line_edit.h12
-rw-r--r--scene/gui/link_button.cpp83
-rw-r--r--scene/gui/link_button.h9
-rw-r--r--scene/gui/popup_menu.cpp39
-rw-r--r--scene/gui/popup_menu.h4
-rw-r--r--scene/gui/rich_text_label.cpp185
-rw-r--r--scene/gui/rich_text_label.h9
-rw-r--r--scene/gui/tab_bar.cpp47
-rw-r--r--scene/gui/tab_bar.h5
-rw-r--r--scene/gui/text_edit.cpp161
-rw-r--r--scene/gui/text_edit.h17
-rw-r--r--scene/gui/tree.cpp100
-rw-r--r--scene/gui/tree.h12
-rw-r--r--scene/gui/video_stream_player.h2
-rw-r--r--scene/main/canvas_item.cpp51
-rw-r--r--scene/main/canvas_item.h11
-rw-r--r--scene/main/node.cpp24
-rw-r--r--scene/main/scene_tree.cpp8
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/register_scene_types.cpp21
-rw-r--r--scene/resources/bone_map.cpp172
-rw-r--r--scene/resources/bone_map.h (renamed from editor/plugins/font_editor_plugin.h)60
-rw-r--r--scene/resources/default_theme/default_theme.cpp59
-rw-r--r--scene/resources/font.cpp2310
-rw-r--r--scene/resources/font.h264
-rw-r--r--scene/resources/primitive_meshes.cpp118
-rw-r--r--scene/resources/primitive_meshes.h35
-rw-r--r--scene/resources/skeleton_profile.cpp514
-rw-r--r--scene/resources/skeleton_profile.h (renamed from editor/plugins/ot_features_plugin.h)102
-rw-r--r--scene/resources/text_file.cpp2
-rw-r--r--scene/resources/text_line.cpp42
-rw-r--r--scene/resources/text_line.h6
-rw-r--r--scene/resources/text_paragraph.cpp99
-rw-r--r--scene/resources/text_paragraph.h8
-rw-r--r--scene/resources/texture.cpp29
-rw-r--r--scene/resources/texture.h3
-rw-r--r--scene/resources/tile_set.cpp11
-rw-r--r--scene/resources/visual_shader_particle_nodes.cpp6
-rw-r--r--scene/resources/world_3d.cpp1
-rw-r--r--servers/rendering/SCsub1
-rw-r--r--servers/rendering/dummy/SCsub7
-rw-r--r--servers/rendering/dummy/environment/fog.h55
-rw-r--r--servers/rendering/dummy/environment/gi.h3
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h9
-rw-r--r--servers/rendering/dummy/storage/SCsub5
-rw-r--r--servers/rendering/dummy/storage/material_storage.h3
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h7
-rw-r--r--servers/rendering/dummy/storage/texture_storage.cpp43
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h9
-rw-r--r--servers/rendering/dummy/storage/utilities.h (renamed from servers/rendering/dummy/rasterizer_storage_dummy.h)96
-rw-r--r--servers/rendering/environment/renderer_fog.h53
-rw-r--r--servers/rendering/environment/renderer_gi.h4
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp21
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.cpp6
-rw-r--r--servers/rendering/renderer_canvas_render.h8
-rw-r--r--servers/rendering/renderer_compositor.h6
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h8
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp128
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h83
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp32
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h15
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp80
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h10
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp3
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h5
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp53
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h10
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp3
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp15
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h12
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp74
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp58
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h19
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h222
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/SCsub2
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/SCsub2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp38
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h86
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp32
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp43
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp (renamed from servers/rendering/renderer_rd/renderer_storage_rd.cpp)430
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.h122
-rw-r--r--servers/rendering/renderer_scene_cull.cpp24
-rw-r--r--servers/rendering/renderer_scene_cull.h32
-rw-r--r--servers/rendering/renderer_viewport.cpp8
-rw-r--r--servers/rendering/rendering_server_default.cpp51
-rw-r--r--servers/rendering/rendering_server_default.h11
-rw-r--r--servers/rendering/rendering_server_globals.cpp3
-rw-r--r--servers/rendering/rendering_server_globals.h5
-rw-r--r--servers/rendering/storage/light_storage.h1
-rw-r--r--servers/rendering/storage/material_storage.h4
-rw-r--r--servers/rendering/storage/mesh_storage.h4
-rw-r--r--servers/rendering/storage/particles_storage.h1
-rw-r--r--servers/rendering/storage/texture_storage.h11
-rw-r--r--servers/rendering/storage/utilities.cpp (renamed from servers/rendering/renderer_storage.cpp)16
-rw-r--r--servers/rendering/storage/utilities.h (renamed from servers/rendering/renderer_storage.h)196
-rw-r--r--servers/text/text_server_extension.cpp30
-rw-r--r--servers/text/text_server_extension.h10
-rw-r--r--servers/text_server.cpp6
-rw-r--r--servers/text_server.h7
-rw-r--r--servers/xr/xr_interface_extension.cpp2
-rw-r--r--tests/core/math/test_plane.h172
-rw-r--r--tests/core/object/test_class_db.h12
-rw-r--r--tests/core/string/test_string.h75
-rw-r--r--tests/scene/test_theme.h2
-rw-r--r--tests/test_main.cpp1
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS.hh165
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh84
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh46
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh58
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh70
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh77
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh14
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh32
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh14
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh35
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh281
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh17
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh113
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh35
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh217
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh35
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh244
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh36
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh227
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh52
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh38
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh420
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh314
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh79
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh79
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh98
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh124
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh140
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh329
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh8
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh258
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/Glyph.hh233
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh48
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh216
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh72
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh90
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf.hh388
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/loca.hh43
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/path-builder.hh135
-rw-r--r--thirdparty/harfbuzz/src/graph/graph.hh860
-rw-r--r--thirdparty/harfbuzz/src/graph/serialize.hh249
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh38
-rw-r--r--thirdparty/harfbuzz/src/hb-array.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-bimap.hh9
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set-invertible.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-serialize.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-verify.cc28
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc37
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.h34
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh44
-rw-r--r--thirdparty/harfbuzz/src/hb-cache.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-config.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc56
-rw-r--r--thirdparty/harfbuzz/src/hb-cplusplus.hh192
-rw-r--r--thirdparty/harfbuzz/src/hb-directwrite.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.cc65
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-face.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-face.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc177
-rw-r--r--thirdparty/harfbuzz/src/hb-font.h6
-rw-r--r--thirdparty/harfbuzz/src/hb-font.hh81
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc158
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.h9
-rw-r--r--thirdparty/harfbuzz/src/hb-iter.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-map.cc38
-rw-r--r--thirdparty/harfbuzz/src/hb-map.h6
-rw-r--r--thirdparty/harfbuzz/src/hb-map.hh134
-rw-r--r--thirdparty/harfbuzz/src/hb-meta.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-null.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cmap-table.hh77
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc164
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh1330
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh9
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh233
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh3090
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh421
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc48
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-language-static.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-table.hh36
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-os2-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh603
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc501
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh431
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh396
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh115
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh492
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh177
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh849
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc11
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh)80
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh)6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh118
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh)141
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh)8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc)27
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh)8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-default.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc)6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc)6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc)6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh589
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc560
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc)356
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh66
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh428
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc)29
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh553
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc)74
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc)31
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh)13
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc)16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh931
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh)12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc)16
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc)4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh)8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper.hh (renamed from thirdparty/harfbuzz/src/hb-ot-shape-complex.hh)85
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc25
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh132
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh11
-rw-r--r--thirdparty/harfbuzz/src/hb-repacker.hh1054
-rw-r--r--thirdparty/harfbuzz/src/hb-serialize.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-set-digest.hh30
-rw-r--r--thirdparty/harfbuzz/src/hb-set.cc20
-rw-r--r--thirdparty/harfbuzz/src/hb-set.h3
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh1
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc20
-rw-r--r--thirdparty/harfbuzz/src/hb-shaper.cc16
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc3
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.cc15
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc48
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc120
-rw-r--r--thirdparty/harfbuzz/src/hb-ucd-table.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h6
-rw-r--r--thirdparty/harfbuzz/src/hb.hh5
736 files changed, 37636 insertions, 25233 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 3df4409041..0c6a140e28 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -127,6 +127,8 @@ jobs:
- name: Unit tests
if: ${{ matrix.tests }}
run: |
+ ${{ matrix.bin }} --version
+ ${{ matrix.bin }} --help
${{ matrix.bin }} --test --headless
# Check class reference
diff --git a/.github/workflows/macos_builds.yml b/.github/workflows/macos_builds.yml
index 68623f2770..9b8ffc45a7 100644
--- a/.github/workflows/macos_builds.yml
+++ b/.github/workflows/macos_builds.yml
@@ -5,7 +5,7 @@ on: [push, pull_request]
env:
# Only used for the cache key. Increment version to force clean build.
GODOT_BASE_BRANCH: master-v3
- SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
+ SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes use_volk=yes
concurrency:
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
@@ -58,6 +58,8 @@ jobs:
- name: Unit tests
if: ${{ matrix.tests }}
run: |
+ ${{ matrix.bin }} --version
+ ${{ matrix.bin }} --help
${{ matrix.bin }} --test
- name: Prepare artifact
diff --git a/.github/workflows/windows_builds.yml b/.github/workflows/windows_builds.yml
index 4919f34cf0..e04d49adde 100644
--- a/.github/workflows/windows_builds.yml
+++ b/.github/workflows/windows_builds.yml
@@ -64,6 +64,8 @@ jobs:
- name: Unit tests
if: ${{ matrix.tests }}
run: |
+ ${{ matrix.bin }} --version
+ ${{ matrix.bin }} --help
${{ matrix.bin }} --test
- name: Prepare artifact
diff --git a/SConstruct b/SConstruct
index 28395227d2..50cb43b218 100644
--- a/SConstruct
+++ b/SConstruct
@@ -788,7 +788,8 @@ if selected_platform in platform_list:
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
- SConscript("editor/SCsub")
+ if env["tools"]:
+ SConscript("editor/SCsub")
SConscript("drivers/SCsub")
SConscript("platform/SCsub")
diff --git a/core/SCsub b/core/SCsub
index 3814c72877..df3e7a547a 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -129,9 +129,8 @@ if env["builtin_zstd"]:
"decompress/zstd_decompress_block.c",
"decompress/zstd_decompress.c",
]
- if env["platform"] in ["android", "linuxbsd", "osx"]:
+ if env["platform"] in ["android", "iphone", "linuxbsd", "osx"]:
# Match platforms with ZSTD_ASM_SUPPORTED in common/portability_macros.h
- # iOS x86_64 should be supported in theory, but it fails arm64 build, seems to use host S_compiler.
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index b5f4a1c0f6..26ecd41353 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -147,7 +147,7 @@ void ResourceLoader::_bind_methods() {
////// ResourceSaver //////
-Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
+Error ResourceSaver::save(const String &p_path, const Ref<Resource> &p_resource, BitField<SaverFlags> p_flags) {
ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + String(p_path) + "'.");
return ::ResourceSaver::save(p_path, p_resource, p_flags);
}
@@ -179,14 +179,14 @@ void ResourceSaver::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver);
- BIND_ENUM_CONSTANT(FLAG_NONE);
- BIND_ENUM_CONSTANT(FLAG_RELATIVE_PATHS);
- BIND_ENUM_CONSTANT(FLAG_BUNDLE_RESOURCES);
- BIND_ENUM_CONSTANT(FLAG_CHANGE_PATH);
- BIND_ENUM_CONSTANT(FLAG_OMIT_EDITOR_PROPERTIES);
- BIND_ENUM_CONSTANT(FLAG_SAVE_BIG_ENDIAN);
- BIND_ENUM_CONSTANT(FLAG_COMPRESS);
- BIND_ENUM_CONSTANT(FLAG_REPLACE_SUBRESOURCE_PATHS);
+ BIND_BITFIELD_FLAG(FLAG_NONE);
+ BIND_BITFIELD_FLAG(FLAG_RELATIVE_PATHS);
+ BIND_BITFIELD_FLAG(FLAG_BUNDLE_RESOURCES);
+ BIND_BITFIELD_FLAG(FLAG_CHANGE_PATH);
+ BIND_BITFIELD_FLAG(FLAG_OMIT_EDITOR_PROPERTIES);
+ BIND_BITFIELD_FLAG(FLAG_SAVE_BIG_ENDIAN);
+ BIND_BITFIELD_FLAG(FLAG_COMPRESS);
+ BIND_BITFIELD_FLAG(FLAG_REPLACE_SUBRESOURCE_PATHS);
}
////// OS //////
@@ -1840,13 +1840,14 @@ void Thread::_start_func(void *ud) {
ERR_FAIL_MSG(vformat("Could not call function '%s' on previously freed instance to start thread %s.", t->target_callable.get_method(), t->get_id()));
}
- ::Thread::set_name(t->target_callable.get_method());
+ String func_name = t->target_callable.is_custom() ? t->target_callable.get_custom()->get_as_text() : String(t->target_callable.get_method());
+ ::Thread::set_name(func_name);
Callable::CallError ce;
t->target_callable.call(nullptr, 0, t->ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
t->running.clear();
- ERR_FAIL_MSG("Could not call function '" + t->target_callable.get_method().operator String() + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + ".");
+ ERR_FAIL_MSG("Could not call function '" + func_name + "' to start thread " + t->get_id() + ": " + Variant::get_callable_error_text(t->target_callable, nullptr, 0, ce) + ".");
}
t->running.clear();
diff --git a/core/core_bind.h b/core/core_bind.h
index 99e14a75f5..c116ac4986 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -109,7 +109,7 @@ public:
static ResourceSaver *get_singleton() { return singleton; }
- Error save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags);
+ Error save(const String &p_path, const Ref<Resource> &p_resource, BitField<SaverFlags> p_flags);
Vector<String> get_recognized_extensions(const Ref<Resource> &p_resource);
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
@@ -719,7 +719,7 @@ public:
VARIANT_ENUM_CAST(core_bind::ResourceLoader::ThreadLoadStatus);
VARIANT_ENUM_CAST(core_bind::ResourceLoader::CacheMode);
-VARIANT_ENUM_CAST(core_bind::ResourceSaver::SaverFlags);
+VARIANT_BITFIELD_CAST(core_bind::ResourceSaver::SaverFlags);
VARIANT_ENUM_CAST(core_bind::OS::VideoDriver);
VARIANT_ENUM_CAST(core_bind::OS::Weekday);
diff --git a/core/doc_data.cpp b/core/doc_data.cpp
index 1e72ad1090..89e7a8dc71 100644
--- a/core/doc_data.cpp
+++ b/core/doc_data.cpp
@@ -38,7 +38,7 @@ void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const Proper
} else {
p_method.return_type += "*";
}
- } else if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ } else if (p_retinfo.type == Variant::INT && p_retinfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
p_method.return_enum = p_retinfo.class_name;
if (p_method.return_enum.begins_with("_")) { //proxy class
p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length());
@@ -69,7 +69,7 @@ void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const
} else {
p_argument.type += "*";
}
- } else if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ } else if (p_arginfo.type == Variant::INT && p_arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
p_argument.enumeration = p_arginfo.class_name;
if (p_argument.enumeration.begins_with("_")) { //proxy class
p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length());
diff --git a/core/doc_data.h b/core/doc_data.h
index af20b717d7..1d8d2483e0 100644
--- a/core/doc_data.h
+++ b/core/doc_data.h
@@ -103,6 +103,7 @@ public:
String value;
bool is_value_valid = false;
String enumeration;
+ bool is_bitfield = false;
String description;
bool operator<(const ConstantDoc &p_const) const {
return name < p_const.name;
@@ -111,6 +112,7 @@ public:
struct EnumDoc {
String name = "@unnamed_enum";
+ bool is_bitfield = false;
String description;
Vector<DocData::ConstantDoc> values;
};
@@ -163,6 +165,7 @@ public:
Vector<ConstantDoc> constants;
HashMap<String, String> enums;
Vector<PropertyDoc> properties;
+ Vector<MethodDoc> annotations;
Vector<ThemeItemDoc> theme_properties;
bool is_script_doc = false;
String script_path;
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 9d846f87c2..d5c49b01e9 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -46,7 +46,7 @@ static String get_type_name(const PropertyInfo &p_info) {
return p_info.hint_string + "*";
}
}
- if (p_info.type == Variant::INT && (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM)) {
+ if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD))) {
return String("enum::") + String(p_info.class_name);
}
if (p_info.class_name != StringName()) {
@@ -665,6 +665,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
for (const StringName &F : enum_list) {
Dictionary d2;
d2["name"] = String(F);
+ d2["is_bitfield"] = ClassDB::is_enum_bitfield(class_name, F);
Array values;
List<StringName> enum_constant_list;
diff --git a/core/input/input.h b/core/input/input.h
index f02f2abae5..3ad8c91ddf 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -110,7 +110,7 @@ private:
bool emulate_touch_from_mouse = false;
bool emulate_mouse_from_touch = false;
bool use_input_buffering = false;
- bool use_accumulated_input = false;
+ bool use_accumulated_input = true;
int mouse_from_touch_index = -1;
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 32e025417e..3c104c2c86 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -741,6 +741,14 @@ float InputEventMouseMotion::get_pressure() const {
return pressure;
}
+void InputEventMouseMotion::set_pen_inverted(bool p_inverted) {
+ pen_inverted = p_inverted;
+}
+
+bool InputEventMouseMotion::get_pen_inverted() const {
+ return pen_inverted;
+}
+
void InputEventMouseMotion::set_relative(const Vector2 &p_relative) {
relative = p_relative;
}
@@ -768,6 +776,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_position(p_xform.xform(get_position() + p_local_ofs));
mm->set_pressure(get_pressure());
+ mm->set_pen_inverted(get_pen_inverted());
mm->set_tilt(get_tilt());
mm->set_global_position(get_global_position());
@@ -805,9 +814,9 @@ String InputEventMouseMotion::to_string() {
break;
}
- // Work around the fact vformat can only take 5 substitutions but 6 need to be passed.
- String mask_and_position = vformat("button_mask=%s, position=(%s)", button_mask_string, String(get_position()));
- return vformat("InputEventMouseMotion: %s, relative=(%s), velocity=(%s), pressure=%.2f, tilt=(%s)", mask_and_position, String(get_relative()), String(get_velocity()), get_pressure(), String(get_tilt()));
+ // Work around the fact vformat can only take 5 substitutions but 7 need to be passed.
+ String mask_and_position_and_relative = vformat("button_mask=%s, position=(%s), relative=(%s)", button_mask_string, String(get_position()), String(get_relative()));
+ return vformat("InputEventMouseMotion: %s, velocity=(%s), pressure=%.2f, tilt=(%s), pen_inverted=(%d)", mask_and_position_and_relative, String(get_velocity()), get_pressure(), String(get_tilt()), get_pen_inverted());
}
bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) {
@@ -859,6 +868,9 @@ void InputEventMouseMotion::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMouseMotion::set_pressure);
ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMouseMotion::get_pressure);
+ ClassDB::bind_method(D_METHOD("set_pen_inverted", "pen_inverted"), &InputEventMouseMotion::set_pen_inverted);
+ ClassDB::bind_method(D_METHOD("get_pen_inverted"), &InputEventMouseMotion::get_pen_inverted);
+
ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative);
ClassDB::bind_method(D_METHOD("get_relative"), &InputEventMouseMotion::get_relative);
@@ -867,6 +879,7 @@ void InputEventMouseMotion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "tilt"), "set_tilt", "get_tilt");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure"), "set_pressure", "get_pressure");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pen_inverted"), "set_pen_inverted", "get_pen_inverted");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "relative", PROPERTY_HINT_NONE, "suffix:px"), "set_relative", "get_relative");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_velocity", "get_velocity");
}
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 114db46623..59a2df497c 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -272,6 +272,7 @@ class InputEventMouseMotion : public InputEventMouse {
float pressure = 0;
Vector2 relative;
Vector2 velocity;
+ bool pen_inverted = false;
protected:
static void _bind_methods();
@@ -283,6 +284,9 @@ public:
void set_pressure(float p_pressure);
float get_pressure() const;
+ void set_pen_inverted(bool p_inverted);
+ bool get_pen_inverted() const;
+
void set_relative(const Vector2 &p_relative);
Vector2 get_relative() const;
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 433a7efb21..0a900078b7 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -181,6 +181,10 @@ Error DirAccess::make_dir_recursive(String p_dir) {
return OK;
}
+DirAccess::AccessType DirAccess::get_access_type() const {
+ return _access_type;
+}
+
String DirAccess::fix_path(String p_path) const {
switch (_access_type) {
case ACCESS_RESOURCES: {
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 0125f011b5..22017efaa3 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -57,6 +57,7 @@ protected:
String _get_root_path() const;
String _get_root_string() const;
+ AccessType get_access_type() const;
String fix_path(String p_path) const;
template <class T>
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 7d8da1b11c..da25f23917 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -388,9 +388,7 @@ String FileAccess::get_as_utf8_string() const {
w[len] = 0;
String s;
- if (s.parse_utf8((const char *)w)) {
- return String();
- }
+ s.parse_utf8((const char *)w);
return s;
}
@@ -516,7 +514,6 @@ String FileAccess::get_pascal_string() {
String ret;
ret.parse_utf8(cs.ptr());
-
return ret;
}
diff --git a/core/io/image.cpp b/core/io/image.cpp
index f065dac212..473d70bd7c 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -2284,6 +2284,21 @@ Error Image::load(const String &p_path) {
return ImageLoader::load_image(p_path, this);
}
+Ref<Image> Image::load_from_file(const String &p_path) {
+#ifdef DEBUG_ENABLED
+ if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
+ WARN_PRINT("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource.");
+ }
+#endif
+ Ref<Image> image;
+ image.instantiate();
+ Error err = ImageLoader::load_image(p_path, image);
+ if (err != OK) {
+ ERR_FAIL_V_MSG(Ref<Image>(), vformat("Failed to load image. Error %d", err));
+ }
+ return image;
+}
+
Error Image::save_png(const String &p_path) const {
if (save_png_func == nullptr) {
return ERR_UNAVAILABLE;
@@ -3183,6 +3198,7 @@ void Image::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_empty"), &Image::is_empty);
ClassDB::bind_method(D_METHOD("load", "path"), &Image::load);
+ ClassDB::bind_static_method("Image", D_METHOD("load_from_file", "path"), &Image::load_from_file);
ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png);
ClassDB::bind_method(D_METHOD("save_png_to_buffer"), &Image::save_png_to_buffer);
ClassDB::bind_method(D_METHOD("save_jpg", "path", "quality"), &Image::save_jpg, DEFVAL(0.75));
diff --git a/core/io/image.h b/core/io/image.h
index 2cad26f3e9..6b323e5eb3 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -290,6 +290,7 @@ public:
Vector<uint8_t> get_data() const;
Error load(const String &p_path);
+ static Ref<Image> load_from_file(const String &p_path);
Error save_png(const String &p_path) const;
Error save_jpg(const String &p_path, float p_quality = 0.75) const;
Vector<uint8_t> save_png_to_buffer() const;
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index f71ea5c39e..8ee19f274e 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -78,7 +78,7 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r
ERR_FAIL_COND_V(strlen < 0 || strlen + pad > len, ERR_FILE_EOF);
String str;
- ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(str.parse_utf8((const char *)buf, strlen) != OK, ERR_INVALID_DATA);
r_string = str;
// Add padding
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 7b43193f47..154b55f5e7 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -72,11 +72,11 @@ void XMLParser::_parse_closing_xml_element() {
node_empty = false;
attributes.clear();
- ++P;
+ next_char();
const char *pBeginClose = P;
while (*P && *P != '>') {
- ++P;
+ next_char();
}
node_name = String::utf8(pBeginClose, (int)(P - pBeginClose));
@@ -85,7 +85,7 @@ void XMLParser::_parse_closing_xml_element() {
#endif
if (*P) {
- ++P;
+ next_char();
}
}
@@ -95,12 +95,12 @@ void XMLParser::_ignore_definition() {
char *F = P;
// move until end marked with '>' reached
while (*P && *P != '>') {
- ++P;
+ next_char();
}
node_name.parse_utf8(F, P - F);
if (*P) {
- ++P;
+ next_char();
}
}
@@ -114,7 +114,7 @@ bool XMLParser::_parse_cdata() {
// skip '<![CDATA['
int count = 0;
while (*P && count < 8) {
- ++P;
+ next_char();
++count;
}
@@ -134,7 +134,7 @@ bool XMLParser::_parse_cdata() {
cDataEnd = P - 2;
}
- ++P;
+ next_char();
}
if (cDataEnd) {
@@ -180,7 +180,7 @@ void XMLParser::_parse_comment() {
} else if (*P == '<') {
++count;
}
- ++P;
+ next_char();
}
if (count) {
@@ -206,7 +206,7 @@ void XMLParser::_parse_opening_xml_element() {
// find end of element
while (*P && *P != '>' && !_is_white_space(*P)) {
- ++P;
+ next_char();
}
const char *endName = P;
@@ -214,7 +214,7 @@ void XMLParser::_parse_opening_xml_element() {
// find attributes
while (*P && *P != '>') {
if (_is_white_space(*P)) {
- ++P;
+ next_char();
} else {
if (*P != '/') {
// we've got an attribute
@@ -223,7 +223,7 @@ void XMLParser::_parse_opening_xml_element() {
const char *attributeNameBegin = P;
while (*P && !_is_white_space(*P) && *P != '=') {
- ++P;
+ next_char();
}
if (!*P) {
@@ -231,12 +231,12 @@ void XMLParser::_parse_opening_xml_element() {
}
const char *attributeNameEnd = P;
- ++P;
+ next_char();
// read the attribute value
// check for quotes and single quotes, thx to murphy
while ((*P != '\"') && (*P != '\'') && *P) {
- ++P;
+ next_char();
}
if (!*P) { // malformatted xml file
@@ -245,16 +245,16 @@ void XMLParser::_parse_opening_xml_element() {
const char attributeQuoteChar = *P;
- ++P;
+ next_char();
const char *attributeValueBegin = P;
while (*P != attributeQuoteChar && *P) {
- ++P;
+ next_char();
}
const char *attributeValueEnd = P;
if (*P) {
- ++P;
+ next_char();
}
Attribute attr;
@@ -268,7 +268,7 @@ void XMLParser::_parse_opening_xml_element() {
attributes.push_back(attr);
} else {
// tag is closed directly
- ++P;
+ next_char();
node_empty = true;
break;
}
@@ -288,7 +288,7 @@ void XMLParser::_parse_opening_xml_element() {
#endif
if (*P) {
- ++P;
+ next_char();
}
}
@@ -298,7 +298,7 @@ void XMLParser::_parse_current_node() {
// more forward until '<' found
while (*P != '<' && *P) {
- ++P;
+ next_char();
}
if (P - start > 0) {
@@ -312,7 +312,7 @@ void XMLParser::_parse_current_node() {
return;
}
- ++P;
+ next_char();
// based on current token, parse and report next element
switch (*P) {
@@ -487,6 +487,7 @@ Error XMLParser::open(const String &p_path) {
file->get_buffer((uint8_t *)data, length);
data[length] = 0;
P = data;
+ current_line = 0;
return OK;
}
@@ -523,10 +524,7 @@ void XMLParser::close() {
}
int XMLParser::get_current_line() const {
- return 0;
-}
-
-XMLParser::XMLParser() {
+ return current_line;
}
XMLParser::~XMLParser() {
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index da14ee8eae..aea252ddc7 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -68,6 +68,7 @@ private:
char *data = nullptr;
char *P = nullptr;
uint64_t length = 0;
+ uint64_t current_line = 0;
String node_name;
bool node_empty = false;
NodeType node_type = NODE_NONE;
@@ -88,6 +89,13 @@ private:
void _parse_opening_xml_element();
void _parse_current_node();
+ _FORCE_INLINE_ void next_char() {
+ if (*P == '\n') {
+ current_line++;
+ }
+ P++;
+ }
+
static void _bind_methods();
public:
@@ -113,7 +121,6 @@ public:
void close();
- XMLParser();
~XMLParser();
};
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 419056d7d6..e230b69dc9 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -891,7 +891,7 @@ Expression::ENode *Expression::_parse_expression() {
case TK_PERIOD: {
//named indexing or function call
_get_token(tk);
- if (tk.type != TK_IDENTIFIER) {
+ if (tk.type != TK_IDENTIFIER && tk.type != TK_BUILTIN_FUNC) {
_set_error("Expected identifier after '.'");
return nullptr;
}
diff --git a/core/math/octree.h b/core/math/octree.h
deleted file mode 100644
index 8dd103f109..0000000000
--- a/core/math/octree.h
+++ /dev/null
@@ -1,1271 +0,0 @@
-/*************************************************************************/
-/* octree.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef OCTREE_H
-#define OCTREE_H
-
-#include "core/math/aabb.h"
-#include "core/math/geometry_3d.h"
-#include "core/math/vector3.h"
-#include "core/string/print_string.h"
-#include "core/templates/list.h"
-#include "core/templates/rb_map.h"
-#include "core/variant/variant.h"
-
-typedef uint32_t OctreeElementID;
-
-#define OCTREE_ELEMENT_INVALID_ID 0
-#define OCTREE_SIZE_LIMIT 1e15
-
-template <class T, bool use_pairs = false, class AL = DefaultAllocator>
-class Octree {
-public:
- typedef void *(*PairCallback)(void *, OctreeElementID, T *, int, OctreeElementID, T *, int);
- typedef void (*UnpairCallback)(void *, OctreeElementID, T *, int, OctreeElementID, T *, int, void *);
-
-private:
- enum {
- NEG = 0,
- POS = 1,
- };
-
- enum {
- OCTANT_NX_NY_NZ,
- OCTANT_PX_NY_NZ,
- OCTANT_NX_PY_NZ,
- OCTANT_PX_PY_NZ,
- OCTANT_NX_NY_PZ,
- OCTANT_PX_NY_PZ,
- OCTANT_NX_PY_PZ,
- OCTANT_PX_PY_PZ
- };
-
- struct PairKey {
- union {
- struct {
- OctreeElementID A;
- OctreeElementID B;
- };
- uint64_t key;
- };
-
- _FORCE_INLINE_ bool operator<(const PairKey &p_pair) const {
- return key < p_pair.key;
- }
-
- _FORCE_INLINE_ PairKey(OctreeElementID p_A, OctreeElementID p_B) {
- if (p_A < p_B) {
- A = p_A;
- B = p_B;
- } else {
- B = p_A;
- A = p_B;
- }
- }
-
- _FORCE_INLINE_ PairKey() {}
- };
-
- struct Element;
-
- struct Octant {
- // cached for FAST plane check
- AABB aabb;
-
- uint64_t last_pass = 0;
- Octant *parent = nullptr;
- Octant *children[8] = { nullptr };
-
- int children_count = 0; // cache for amount of children (fast check for removal)
- int parent_index = -1; // cache for parent index (fast check for removal)
-
- List<Element *, AL> pairable_elements;
- List<Element *, AL> elements;
-
- Octant() {}
- ~Octant() {}
- };
-
- struct PairData;
-
- struct Element {
- Octree *octree = nullptr;
-
- T *userdata = nullptr;
- int subindex = 0;
- bool pairable = false;
- uint32_t pairable_mask = 0;
- uint32_t pairable_type = 0;
-
- uint64_t last_pass = 0;
- OctreeElementID _id = 0;
- Octant *common_parent = nullptr;
-
- AABB aabb;
- AABB container_aabb;
-
- List<PairData *, AL> pair_list;
-
- struct OctantOwner {
- Octant *octant = nullptr;
- typename List<Element *, AL>::Element *E;
- }; // an element can be in max 8 octants
-
- List<OctantOwner, AL> octant_owners;
-
- Element() {}
- };
-
- struct PairData {
- int refcount;
- bool intersect;
- Element *A, *B;
- void *ud = nullptr;
- typename List<PairData *, AL>::Element *eA, *eB;
- };
-
- typedef HashMap<OctreeElementID, Element, Comparator<OctreeElementID>, AL> ElementMap;
- typedef HashMap<PairKey, PairData, Comparator<PairKey>, AL> PairMap;
- ElementMap element_map;
- PairMap pair_map;
-
- PairCallback pair_callback = nullptr;
- UnpairCallback unpair_callback = nullptr;
- void *pair_callback_userdata = nullptr;
- void *unpair_callback_userdata = nullptr;
-
- OctreeElementID last_element_id = 1;
- uint64_t pass = 1;
-
- real_t unit_size = 1.0;
- Octant *root = nullptr;
- int octant_count = 0;
- int pair_count = 0;
-
- _FORCE_INLINE_ void _pair_check(PairData *p_pair) {
- bool intersect = p_pair->A->aabb.intersects_inclusive(p_pair->B->aabb);
-
- if (intersect != p_pair->intersect) {
- if (intersect) {
- if (pair_callback) {
- p_pair->ud = pair_callback(pair_callback_userdata, p_pair->A->_id, p_pair->A->userdata, p_pair->A->subindex, p_pair->B->_id, p_pair->B->userdata, p_pair->B->subindex);
- }
- pair_count++;
- } else {
- if (unpair_callback) {
- unpair_callback(pair_callback_userdata, p_pair->A->_id, p_pair->A->userdata, p_pair->A->subindex, p_pair->B->_id, p_pair->B->userdata, p_pair->B->subindex, p_pair->ud);
- }
- pair_count--;
- }
-
- p_pair->intersect = intersect;
- }
- }
-
- _FORCE_INLINE_ void _pair_reference(Element *p_A, Element *p_B) {
- if (p_A == p_B || (p_A->userdata == p_B->userdata && p_A->userdata)) {
- return;
- }
-
- if (!(p_A->pairable_type & p_B->pairable_mask) &&
- !(p_B->pairable_type & p_A->pairable_mask)) {
- return; // none can pair with none
- }
-
- PairKey key(p_A->_id, p_B->_id);
- typename PairMap::Element *E = pair_map.find(key);
-
- if (!E) {
- PairData pdata;
- pdata.refcount = 1;
- pdata.A = p_A;
- pdata.B = p_B;
- pdata.intersect = false;
- E = pair_map.insert(key, pdata);
- E->get().eA = p_A->pair_list.push_back(&E->get());
- E->get().eB = p_B->pair_list.push_back(&E->get());
- } else {
- E->get().refcount++;
- }
- }
-
- _FORCE_INLINE_ void _pair_unreference(Element *p_A, Element *p_B) {
- if (p_A == p_B) {
- return;
- }
-
- PairKey key(p_A->_id, p_B->_id);
- typename PairMap::Element *E = pair_map.find(key);
- if (!E) {
- return; // no pair
- }
-
- E->get().refcount--;
-
- if (E->get().refcount == 0) {
- // bye pair
-
- if (E->get().intersect) {
- if (unpair_callback) {
- unpair_callback(pair_callback_userdata, p_A->_id, p_A->userdata, p_A->subindex, p_B->_id, p_B->userdata, p_B->subindex, E->get().ud);
- }
-
- pair_count--;
- }
-
- if (p_A == E->get().B) {
- //may be reaching inverted
- SWAP(p_A, p_B);
- }
-
- p_A->pair_list.erase(E->get().eA);
- p_B->pair_list.erase(E->get().eB);
- pair_map.erase(E);
- }
- }
-
- _FORCE_INLINE_ void _element_check_pairs(Element *p_element) {
- typename List<PairData *, AL>::Element *E = p_element->pair_list.front();
- while (E) {
- _pair_check(E->get());
- E = E->next();
- }
- }
-
- _FORCE_INLINE_ void _optimize() {
- while (root && root->children_count < 2 && !root->elements.size() && !(use_pairs && root->pairable_elements.size())) {
- Octant *new_root = nullptr;
- if (root->children_count == 1) {
- for (int i = 0; i < 8; i++) {
- if (root->children[i]) {
- new_root = root->children[i];
- root->children[i] = nullptr;
- break;
- }
- }
- ERR_FAIL_COND(!new_root);
- new_root->parent = nullptr;
- new_root->parent_index = -1;
- }
-
- memdelete_allocator<Octant, AL>(root);
- octant_count--;
- root = new_root;
- }
- }
-
- void _insert_element(Element *p_element, Octant *p_octant);
- void _ensure_valid_root(const AABB &p_aabb);
- bool _remove_element_from_octant(Element *p_element, Octant *p_octant, Octant *p_limit = nullptr);
- void _remove_element(Element *p_element);
- void _pair_element(Element *p_element, Octant *p_octant);
- void _unpair_element(Element *p_element, Octant *p_octant);
-
- struct _CullConvexData {
- const Plane *planes;
- int plane_count;
- const Vector3 *points;
- int point_count;
- T **result_array;
- int *result_idx = nullptr;
- int result_max;
- uint32_t mask;
- };
-
- void _cull_convex(Octant *p_octant, _CullConvexData *p_cull);
- void _cull_aabb(Octant *p_octant, const AABB &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
- void _cull_segment(Octant *p_octant, const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
- void _cull_point(Octant *p_octant, const Vector3 &p_point, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask);
-
- void _remove_tree(Octant *p_octant) {
- if (!p_octant) {
- return;
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i]) {
- _remove_tree(p_octant->children[i]);
- }
- }
-
- memdelete_allocator<Octant, AL>(p_octant);
- }
-
-public:
- OctreeElementID create(T *p_userdata, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1);
- void move(OctreeElementID p_id, const AABB &p_aabb);
- void set_pairable(OctreeElementID p_id, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t pairable_mask = 1);
- void erase(OctreeElementID p_id);
-
- bool is_pairable(OctreeElementID p_id) const;
- T *get(OctreeElementID p_id) const;
- int get_subindex(OctreeElementID p_id) const;
-
- int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask = 0xFFFFFFFF);
- int cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF);
- int cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF);
-
- int cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF);
-
- void set_pair_callback(PairCallback p_callback, void *p_userdata);
- void set_unpair_callback(UnpairCallback p_callback, void *p_userdata);
-
- int get_octant_count() const { return octant_count; }
- int get_pair_count() const { return pair_count; }
- Octree(real_t p_unit_size = 1.0);
- ~Octree() { _remove_tree(root); }
-};
-
-/* PRIVATE FUNCTIONS */
-
-template <class T, bool use_pairs, class AL>
-T *Octree<T, use_pairs, AL>::get(OctreeElementID p_id) const {
- const typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND_V(!E, nullptr);
- return E->get().userdata;
-}
-
-template <class T, bool use_pairs, class AL>
-bool Octree<T, use_pairs, AL>::is_pairable(OctreeElementID p_id) const {
- const typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND_V(!E, false);
- return E->get().pairable;
-}
-
-template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::get_subindex(OctreeElementID p_id) const {
- const typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND_V(!E, -1);
- return E->get().subindex;
-}
-
-#define OCTREE_DIVISOR 4
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_octant) {
- real_t element_size = p_element->aabb.get_longest_axis_size() * 1.01; // avoid precision issues
-
- if (p_octant->aabb.size.x / OCTREE_DIVISOR < element_size) {
- //if (p_octant->aabb.size.x*0.5 < element_size) {
- /* at smallest possible size for the element */
- typename Element::OctantOwner owner;
- owner.octant = p_octant;
-
- if (use_pairs && p_element->pairable) {
- p_octant->pairable_elements.push_back(p_element);
- owner.E = p_octant->pairable_elements.back();
- } else {
- p_octant->elements.push_back(p_element);
- owner.E = p_octant->elements.back();
- }
-
- p_element->octant_owners.push_back(owner);
-
- if (p_element->common_parent == nullptr) {
- p_element->common_parent = p_octant;
- p_element->container_aabb = p_octant->aabb;
- } else {
- p_element->container_aabb.merge_with(p_octant->aabb);
- }
-
- if (use_pairs && p_octant->children_count > 0) {
- pass++; //elements below this only get ONE reference added
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i]) {
- _pair_element(p_element, p_octant->children[i]);
- }
- }
- }
- } else {
- /* not big enough, send it to subitems */
- int splits = 0;
- bool candidate = p_element->common_parent == nullptr;
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i]) {
- /* element exists, go straight to it */
- if (p_octant->children[i]->aabb.intersects_inclusive(p_element->aabb)) {
- _insert_element(p_element, p_octant->children[i]);
- splits++;
- }
- } else {
- /* check against AABB where child should be */
-
- AABB aabb = p_octant->aabb;
- aabb.size *= 0.5;
-
- if (i & 1) {
- aabb.position.x += aabb.size.x;
- }
- if (i & 2) {
- aabb.position.y += aabb.size.y;
- }
- if (i & 4) {
- aabb.position.z += aabb.size.z;
- }
-
- if (aabb.intersects_inclusive(p_element->aabb)) {
- /* if actually intersects, create the child */
-
- Octant *child = memnew_allocator(Octant, AL);
- p_octant->children[i] = child;
- child->parent = p_octant;
- child->parent_index = i;
-
- child->aabb = aabb;
-
- p_octant->children_count++;
-
- _insert_element(p_element, child);
- octant_count++;
- splits++;
- }
- }
- }
-
- if (candidate && splits > 1) {
- p_element->common_parent = p_octant;
- }
- }
-
- if (use_pairs) {
- typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front();
-
- while (E) {
- _pair_reference(p_element, E->get());
- E = E->next();
- }
-
- if (p_element->pairable) {
- // and always test non-pairable if element is pairable
- E = p_octant->elements.front();
- while (E) {
- _pair_reference(p_element, E->get());
- E = E->next();
- }
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) {
- if (!root) {
- // octre is empty
-
- AABB base(Vector3(), Vector3(1.0, 1.0, 1.0) * unit_size);
-
- while (!base.encloses(p_aabb)) {
- if (ABS(base.position.x + base.size.x) <= ABS(base.position.x)) {
- /* grow towards positive */
- base.size *= 2.0;
- } else {
- base.position -= base.size;
- base.size *= 2.0;
- }
- }
-
- root = memnew_allocator(Octant, AL);
-
- root->parent = nullptr;
- root->parent_index = -1;
- root->aabb = base;
-
- octant_count++;
-
- } else {
- AABB base = root->aabb;
-
- while (!base.encloses(p_aabb)) {
- ERR_FAIL_COND_MSG(base.size.x > OCTREE_SIZE_LIMIT, "Octree upper size limit reached, does the AABB supplied contain NAN?");
-
- Octant *gp = memnew_allocator(Octant, AL);
- octant_count++;
- root->parent = gp;
-
- if (ABS(base.position.x + base.size.x) <= ABS(base.position.x)) {
- /* grow towards positive */
- base.size *= 2.0;
- gp->aabb = base;
- gp->children[0] = root;
- root->parent_index = 0;
- } else {
- base.position -= base.size;
- base.size *= 2.0;
- gp->aabb = base;
- gp->children[(1 << 0) | (1 << 1) | (1 << 2)] = root; // add at all-positive
- root->parent_index = (1 << 0) | (1 << 1) | (1 << 2);
- }
-
- gp->children_count = 1;
- root = gp;
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, Octant *p_octant, Octant *p_limit) {
- bool octant_removed = false;
-
- while (true) {
- // check all exit conditions
-
- if (p_octant == p_limit) { // reached limit, nothing to erase, exit
- return octant_removed;
- }
-
- bool unpaired = false;
-
- if (use_pairs && p_octant->last_pass != pass) {
- // check whether we should unpair stuff
- // always test pairable
- typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front();
- while (E) {
- _pair_unreference(p_element, E->get());
- E = E->next();
- }
- if (p_element->pairable) {
- // and always test non-pairable if element is pairable
- E = p_octant->elements.front();
- while (E) {
- _pair_unreference(p_element, E->get());
- E = E->next();
- }
- }
- p_octant->last_pass = pass;
- unpaired = true;
- }
-
- bool removed = false;
-
- Octant *parent = p_octant->parent;
-
- if (p_octant->children_count == 0 && p_octant->elements.is_empty() && p_octant->pairable_elements.is_empty()) {
- // erase octant
-
- if (p_octant == root) { // won't have a parent, just erase
-
- root = nullptr;
- } else {
- ERR_FAIL_INDEX_V(p_octant->parent_index, 8, octant_removed);
-
- parent->children[p_octant->parent_index] = nullptr;
- parent->children_count--;
- }
-
- memdelete_allocator<Octant, AL>(p_octant);
- octant_count--;
- removed = true;
- octant_removed = true;
- }
-
- if (!removed && !unpaired) {
- return octant_removed; // no reason to keep going up anymore! was already visited and was not removed
- }
-
- p_octant = parent;
- }
-
- return octant_removed;
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_unpair_element(Element *p_element, Octant *p_octant) {
- // always test pairable
- typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front();
- while (E) {
- if (E->get()->last_pass != pass) { // only remove ONE reference
- _pair_unreference(p_element, E->get());
- E->get()->last_pass = pass;
- }
- E = E->next();
- }
-
- if (p_element->pairable) {
- // and always test non-pairable if element is pairable
- E = p_octant->elements.front();
- while (E) {
- if (E->get()->last_pass != pass) { // only remove ONE reference
- _pair_unreference(p_element, E->get());
- E->get()->last_pass = pass;
- }
- E = E->next();
- }
- }
-
- p_octant->last_pass = pass;
-
- if (p_octant->children_count == 0) {
- return; // small optimization for leafs
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i]) {
- _unpair_element(p_element, p_octant->children[i]);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_pair_element(Element *p_element, Octant *p_octant) {
- // always test pairable
-
- typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front();
-
- while (E) {
- if (E->get()->last_pass != pass) { // only get ONE reference
- _pair_reference(p_element, E->get());
- E->get()->last_pass = pass;
- }
- E = E->next();
- }
-
- if (p_element->pairable) {
- // and always test non-pairable if element is pairable
- E = p_octant->elements.front();
- while (E) {
- if (E->get()->last_pass != pass) { // only get ONE reference
- _pair_reference(p_element, E->get());
- E->get()->last_pass = pass;
- }
- E = E->next();
- }
- }
- p_octant->last_pass = pass;
-
- if (p_octant->children_count == 0) {
- return; // small optimization for leafs
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i]) {
- _pair_element(p_element, p_octant->children[i]);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_remove_element(Element *p_element) {
- pass++; // will do a new pass for this
-
- typename List<typename Element::OctantOwner, AL>::Element *I = p_element->octant_owners.front();
-
- /* FIRST remove going up normally */
- for (; I; I = I->next()) {
- Octant *o = I->get().octant;
-
- if (!use_pairs) { // small speedup
- o->elements.erase(I->get().E);
- }
-
- _remove_element_from_octant(p_element, o);
- }
-
- /* THEN remove going down */
-
- I = p_element->octant_owners.front();
-
- if (use_pairs) {
- for (; I; I = I->next()) {
- Octant *o = I->get().octant;
-
- // erase children pairs, they are erased ONCE even if repeated
- pass++;
- for (int i = 0; i < 8; i++) {
- if (o->children[i]) {
- _unpair_element(p_element, o->children[i]);
- }
- }
-
- if (p_element->pairable) {
- o->pairable_elements.erase(I->get().E);
- } else {
- o->elements.erase(I->get().E);
- }
- }
- }
-
- p_element->octant_owners.clear();
-
- if (use_pairs) {
- int remaining = p_element->pair_list.size();
- //p_element->pair_list.clear();
- ERR_FAIL_COND(remaining);
- }
-}
-
-template <class T, bool use_pairs, class AL>
-OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) {
-// check for AABB validity
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_V(p_aabb.position.x > 1e15 || p_aabb.position.x < -1e15, 0);
- ERR_FAIL_COND_V(p_aabb.position.y > 1e15 || p_aabb.position.y < -1e15, 0);
- ERR_FAIL_COND_V(p_aabb.position.z > 1e15 || p_aabb.position.z < -1e15, 0);
- ERR_FAIL_COND_V(p_aabb.size.x > 1e15 || p_aabb.size.x < 0.0, 0);
- ERR_FAIL_COND_V(p_aabb.size.y > 1e15 || p_aabb.size.y < 0.0, 0);
- ERR_FAIL_COND_V(p_aabb.size.z > 1e15 || p_aabb.size.z < 0.0, 0);
- ERR_FAIL_COND_V(Math::is_nan(p_aabb.size.x), 0);
- ERR_FAIL_COND_V(Math::is_nan(p_aabb.size.y), 0);
- ERR_FAIL_COND_V(Math::is_nan(p_aabb.size.z), 0);
-
-#endif
- typename ElementMap::Element *E = element_map.insert(last_element_id++,
- Element());
- Element &e = E->get();
-
- e.aabb = p_aabb;
- e.userdata = p_userdata;
- e.subindex = p_subindex;
- e.last_pass = 0;
- e.octree = this;
- e.pairable = p_pairable;
- e.pairable_type = p_pairable_type;
- e.pairable_mask = p_pairable_mask;
- e._id = last_element_id - 1;
-
- if (!e.aabb.has_no_surface()) {
- _ensure_valid_root(p_aabb);
- _insert_element(&e, root);
- if (use_pairs) {
- _element_check_pairs(&e);
- }
- }
-
- return last_element_id - 1;
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) {
-#ifdef DEBUG_ENABLED
- // check for AABB validity
- ERR_FAIL_COND(p_aabb.position.x > 1e15 || p_aabb.position.x < -1e15);
- ERR_FAIL_COND(p_aabb.position.y > 1e15 || p_aabb.position.y < -1e15);
- ERR_FAIL_COND(p_aabb.position.z > 1e15 || p_aabb.position.z < -1e15);
- ERR_FAIL_COND(p_aabb.size.x > 1e15 || p_aabb.size.x < 0.0);
- ERR_FAIL_COND(p_aabb.size.y > 1e15 || p_aabb.size.y < 0.0);
- ERR_FAIL_COND(p_aabb.size.z > 1e15 || p_aabb.size.z < 0.0);
- ERR_FAIL_COND(Math::is_nan(p_aabb.size.x));
- ERR_FAIL_COND(Math::is_nan(p_aabb.size.y));
- ERR_FAIL_COND(Math::is_nan(p_aabb.size.z));
-#endif
- typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND(!E);
- Element &e = E->get();
-
- bool old_has_surf = !e.aabb.has_no_surface();
- bool new_has_surf = !p_aabb.has_no_surface();
-
- if (old_has_surf != new_has_surf) {
- if (old_has_surf) {
- _remove_element(&e); // removing
- e.common_parent = nullptr;
- e.aabb = AABB();
- _optimize();
- } else {
- _ensure_valid_root(p_aabb); // inserting
- e.common_parent = nullptr;
- e.aabb = p_aabb;
- _insert_element(&e, root);
- if (use_pairs) {
- _element_check_pairs(&e);
- }
- }
-
- return;
- }
-
- if (!old_has_surf) { // doing nothing
- return;
- }
-
- // it still is enclosed in the same AABB it was assigned to
- if (e.container_aabb.encloses(p_aabb)) {
- e.aabb = p_aabb;
- if (use_pairs) {
- _element_check_pairs(&e); // must check pairs anyway
- }
-
- return;
- }
-
- AABB combined = e.aabb;
- combined.merge_with(p_aabb);
- _ensure_valid_root(combined);
-
- ERR_FAIL_COND(e.octant_owners.front() == nullptr);
-
- /* FIND COMMON PARENT */
-
- List<typename Element::OctantOwner, AL> owners = e.octant_owners; // save the octant owners
- Octant *common_parent = e.common_parent;
- ERR_FAIL_COND(!common_parent);
-
- //src is now the place towards where insertion is going to happen
- pass++;
-
- while (common_parent && !common_parent->aabb.encloses(p_aabb)) {
- common_parent = common_parent->parent;
- }
-
- ERR_FAIL_COND(!common_parent);
-
- //prepare for reinsert
- e.octant_owners.clear();
- e.common_parent = nullptr;
- e.aabb = p_aabb;
-
- _insert_element(&e, common_parent); // reinsert from this point
-
- pass++;
-
- for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F;) {
- Octant *o = F->get().octant;
- typename List<typename Element::OctantOwner, AL>::Element *N = F->next();
-
- if (use_pairs && e.pairable) {
- o->pairable_elements.erase(F->get().E);
- } else {
- o->elements.erase(F->get().E);
- }
-
- if (_remove_element_from_octant(&e, o, common_parent->parent)) {
- owners.erase(F);
- }
-
- F = N;
- }
-
- if (use_pairs) {
- //unpair child elements in anything that survived
- for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F; F = F->next()) {
- Octant *o = F->get().octant;
-
- // erase children pairs, unref ONCE
- pass++;
- for (int i = 0; i < 8; i++) {
- if (o->children[i]) {
- _unpair_element(&e, o->children[i]);
- }
- }
- }
-
- _element_check_pairs(&e);
- }
-
- _optimize();
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::set_pairable(OctreeElementID p_id, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) {
- typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND(!E);
-
- Element &e = E->get();
-
- if (p_pairable == e.pairable && e.pairable_type == p_pairable_type && e.pairable_mask == p_pairable_mask) {
- return; // no changes, return
- }
-
- if (!e.aabb.has_no_surface()) {
- _remove_element(&e);
- }
-
- e.pairable = p_pairable;
- e.pairable_type = p_pairable_type;
- e.pairable_mask = p_pairable_mask;
- e.common_parent = nullptr;
-
- if (!e.aabb.has_no_surface()) {
- _ensure_valid_root(e.aabb);
- _insert_element(&e, root);
- if (use_pairs) {
- _element_check_pairs(&e);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::erase(OctreeElementID p_id) {
- typename ElementMap::Element *E = element_map.find(p_id);
- ERR_FAIL_COND(!E);
-
- Element &e = E->get();
-
- if (!e.aabb.has_no_surface()) {
- _remove_element(&e);
- }
-
- element_map.erase(p_id);
- _optimize();
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p_cull) {
- if (*p_cull->result_idx == p_cull->result_max) {
- return; //pointless
- }
-
- if (!p_octant->elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->elements.front();
-
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) {
- if (*p_cull->result_idx < p_cull->result_max) {
- p_cull->result_array[*p_cull->result_idx] = e->userdata;
- (*p_cull->result_idx)++;
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- if (use_pairs && !p_octant->pairable_elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->pairable_elements.front();
-
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) {
- if (*p_cull->result_idx < p_cull->result_max) {
- p_cull->result_array[*p_cull->result_idx] = e->userdata;
- (*p_cull->result_idx)++;
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) {
- _cull_convex(p_octant->children[i], p_cull);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (*p_result_idx == p_result_max) {
- return; //pointless
- }
-
- if (!p_octant->elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (p_aabb.intersects_inclusive(e->aabb)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
-
- (*p_result_idx)++;
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- if (use_pairs && !p_octant->pairable_elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->pairable_elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (p_aabb.intersects_inclusive(e->aabb)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
- (*p_result_idx)++;
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_inclusive(p_aabb)) {
- _cull_aabb(p_octant->children[i], p_aabb, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (*p_result_idx == p_result_max) {
- return; //pointless
- }
-
- if (!p_octant->elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (e->aabb.intersects_segment(p_from, p_to)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
- (*p_result_idx)++;
-
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- if (use_pairs && !p_octant->pairable_elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->pairable_elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
-
- e->last_pass = pass;
-
- if (e->aabb.intersects_segment(p_from, p_to)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
-
- (*p_result_idx)++;
-
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- for (int i = 0; i < 8; i++) {
- if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_segment(p_from, p_to)) {
- _cull_segment(p_octant->children[i], p_from, p_to, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_point, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (*p_result_idx == p_result_max) {
- return; //pointless
- }
-
- if (!p_octant->elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
- e->last_pass = pass;
-
- if (e->aabb.has_point(p_point)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
- (*p_result_idx)++;
-
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- if (use_pairs && !p_octant->pairable_elements.is_empty()) {
- typename List<Element *, AL>::Element *I;
- I = p_octant->pairable_elements.front();
- for (; I; I = I->next()) {
- Element *e = I->get();
-
- if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) {
- continue;
- }
-
- e->last_pass = pass;
-
- if (e->aabb.has_point(p_point)) {
- if (*p_result_idx < p_result_max) {
- p_result_array[*p_result_idx] = e->userdata;
- if (p_subindex_array) {
- p_subindex_array[*p_result_idx] = e->subindex;
- }
-
- (*p_result_idx)++;
-
- } else {
- return; // pointless to continue
- }
- }
- }
- }
-
- for (int i = 0; i < 8; i++) {
- //could be optimized..
- if (p_octant->children[i] && p_octant->children[i]->aabb.has_point(p_point)) {
- _cull_point(p_octant->children[i], p_point, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask);
- }
- }
-}
-
-template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask) {
- if (!root || p_convex.size() == 0) {
- return 0;
- }
-
- Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size());
- if (convex_points.size() == 0) {
- return 0;
- }
-
- int result_count = 0;
- pass++;
- _CullConvexData cdata;
- cdata.planes = &p_convex[0];
- cdata.plane_count = p_convex.size();
- cdata.points = &convex_points[0];
- cdata.point_count = convex_points.size();
- cdata.result_array = p_result_array;
- cdata.result_max = p_result_max;
- cdata.result_idx = &result_count;
- cdata.mask = p_mask;
-
- _cull_convex(root, &cdata);
-
- return result_count;
-}
-
-template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (!root) {
- return 0;
- }
-
- int result_count = 0;
- pass++;
- _cull_aabb(root, p_aabb, p_result_array, &result_count, p_result_max, p_subindex_array, p_mask);
-
- return result_count;
-}
-
-template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (!root) {
- return 0;
- }
-
- int result_count = 0;
- pass++;
- _cull_segment(root, p_from, p_to, p_result_array, &result_count, p_result_max, p_subindex_array, p_mask);
-
- return result_count;
-}
-
-template <class T, bool use_pairs, class AL>
-int Octree<T, use_pairs, AL>::cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) {
- if (!root) {
- return 0;
- }
-
- int result_count = 0;
- pass++;
- _cull_point(root, p_point, p_result_array, &result_count, p_result_max, p_subindex_array, p_mask);
-
- return result_count;
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::set_pair_callback(PairCallback p_callback, void *p_userdata) {
- pair_callback = p_callback;
- pair_callback_userdata = p_userdata;
-}
-
-template <class T, bool use_pairs, class AL>
-void Octree<T, use_pairs, AL>::set_unpair_callback(UnpairCallback p_callback, void *p_userdata) {
- unpair_callback = p_callback;
- unpair_callback_userdata = p_userdata;
-}
-
-template <class T, bool use_pairs, class AL>
-Octree<T, use_pairs, AL>::Octree(real_t p_unit_size) {
- unit_size = p_unit_size;
-}
-
-#endif // OCTREE_H
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 3c9f373d12..ac008dad88 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -536,7 +536,7 @@ MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_n
return nullptr;
}
-void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant) {
+void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield) {
OBJTYPE_WLOCK;
ClassInfo *type = classes.getptr(p_class);
@@ -555,13 +555,15 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
enum_name = enum_name.get_slicec('.', 1);
}
- List<StringName> *constants_list = type->enum_map.getptr(enum_name);
+ ClassInfo::EnumInfo *constants_list = type->enum_map.getptr(enum_name);
if (constants_list) {
- constants_list->push_back(p_name);
+ constants_list->constants.push_back(p_name);
+ constants_list->is_bitfield = p_is_bitfield;
} else {
- List<StringName> new_list;
- new_list.push_back(p_name);
+ ClassInfo::EnumInfo new_list;
+ new_list.is_bitfield = p_is_bitfield;
+ new_list.constants.push_back(p_name);
type->enum_map[enum_name] = new_list;
}
}
@@ -645,8 +647,8 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S
ClassInfo *type = classes.getptr(p_class);
while (type) {
- for (KeyValue<StringName, List<StringName>> &E : type->enum_map) {
- List<StringName> &constants_list = E.value;
+ for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
+ List<StringName> &constants_list = E.value.constants;
const List<StringName>::Element *found = constants_list.find(p_name);
if (found) {
return E.key;
@@ -669,7 +671,7 @@ void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums
ClassInfo *type = classes.getptr(p_class);
while (type) {
- for (KeyValue<StringName, List<StringName>> &E : type->enum_map) {
+ for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
p_enums->push_back(E.key);
}
@@ -687,10 +689,10 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_
ClassInfo *type = classes.getptr(p_class);
while (type) {
- const List<StringName> *constants = type->enum_map.getptr(p_enum);
+ const ClassInfo::EnumInfo *constants = type->enum_map.getptr(p_enum);
if (constants) {
- for (const List<StringName>::Element *E = constants->front(); E; E = E->next()) {
+ for (const List<StringName>::Element *E = constants->constants.front(); E; E = E->next()) {
p_constants->push_back(E->get());
}
}
@@ -748,6 +750,25 @@ bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool
return false;
}
+bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
+ OBJTYPE_RLOCK;
+
+ ClassInfo *type = classes.getptr(p_class);
+
+ while (type) {
+ if (type->enum_map.has(p_name) && type->enum_map[p_name].is_bitfield) {
+ return true;
+ }
+ if (p_no_inheritance) {
+ return false;
+ }
+
+ type = type->inherits_ptr;
+ }
+
+ return false;
+}
+
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
OBJTYPE_WLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index f2f73dc674..1d26eb18f1 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -104,7 +104,12 @@ public:
HashMap<StringName, MethodBind *> method_map;
HashMap<StringName, int64_t> constant_map;
- HashMap<StringName, List<StringName>> enum_map;
+ struct EnumInfo {
+ List<StringName> constants;
+ bool is_bitfield = false;
+ };
+
+ HashMap<StringName, EnumInfo> enum_map;
HashMap<StringName, MethodInfo> signal_map;
List<PropertyInfo> property_list;
HashMap<StringName, PropertyInfo> property_map;
@@ -325,15 +330,17 @@ public:
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual = true, const Vector<String> &p_arg_names = Vector<String>(), bool p_object_core = false);
static void get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false);
- static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant);
+ static void bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield = false);
static void get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance = false);
static int64_t get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success = nullptr);
static bool has_integer_constant(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static StringName get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
+ static StringName get_integer_constant_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static void get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance = false);
static void get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance = false);
static bool has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
+ static bool is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance = false);
static void set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values);
static Vector<Error> get_method_error_return_values(const StringName &p_class, const StringName &p_method);
@@ -370,6 +377,9 @@ public:
#define BIND_ENUM_CONSTANT(m_constant) \
::ClassDB::bind_integer_constant(get_class_static(), __constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant);
+#define BIND_BITFIELD_FLAG(m_constant) \
+ ::ClassDB::bind_integer_constant(get_class_static(), __constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
+
_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr) {
}
@@ -401,6 +411,9 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
#define BIND_ENUM_CONSTANT(m_constant) \
::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant);
+#define BIND_BITFIELD_FLAG(m_constant) \
+ ::ClassDB::bind_integer_constant(get_class_static(), StringName(), #m_constant, m_constant, true);
+
#define BIND_METHOD_ERR_RETURN_DOC(m_method, ...)
#endif
diff --git a/core/object/object.h b/core/object/object.h
index 1f6386e6b4..87d042dd7e 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -109,6 +109,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
PROPERTY_USAGE_CATEGORY = 256,
PROPERTY_USAGE_SUBGROUP = 512,
+ PROPERTY_USAGE_CLASS_IS_BITFIELD = 1024,
PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 776a9bfaab..686ab5b8d3 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -350,6 +350,7 @@ public:
LOOKUP_RESULT_CLASS_SIGNAL,
LOOKUP_RESULT_CLASS_ENUM,
LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE,
+ LOOKUP_RESULT_CLASS_ANNOTATION,
LOOKUP_RESULT_MAX
};
@@ -402,6 +403,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
virtual void get_public_functions(List<MethodInfo> *p_functions) const = 0;
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const = 0;
+ virtual void get_public_annotations(List<MethodInfo> *p_annotations) const = 0;
struct ProfilingInfo {
StringName signature;
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index 5af79bbea3..ab8dd6d1ee 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -134,6 +134,7 @@ void ScriptLanguageExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_recognized_extensions);
GDVIRTUAL_BIND(_get_public_functions);
GDVIRTUAL_BIND(_get_public_constants);
+ GDVIRTUAL_BIND(_get_public_annotations);
GDVIRTUAL_BIND(_profiling_start);
GDVIRTUAL_BIND(_profiling_stop);
@@ -160,6 +161,7 @@ void ScriptLanguageExtension::_bind_methods() {
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_SIGNAL);
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ENUM);
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE);
+ BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_ANNOTATION);
BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX);
BIND_ENUM_CONSTANT(LOCATION_LOCAL);
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 7eea48370e..2c53139ec2 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -580,6 +580,15 @@ public:
p_constants->push_back(Pair<String, Variant>(d["name"], d["value"]));
}
}
+ GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_annotations)
+ virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override {
+ TypedArray<Dictionary> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_public_annotations, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ MethodInfo mi = MethodInfo::from_dict(ret[i]);
+ p_annotations->push_back(mi);
+ }
+ }
EXBIND0(profiling_start)
EXBIND0(profiling_stop)
diff --git a/core/os/os.h b/core/os/os.h
index af6c38cbe0..0428f6df2a 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -160,6 +160,7 @@ public:
virtual String get_name() const = 0;
virtual List<String> get_cmdline_args() const { return _cmdline; }
+ virtual List<String> get_cmdline_platform_args() const { return List<String>(); }
virtual String get_model_name() const;
bool is_layered_allowed() const { return _allow_layered; }
diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp
index 238897c2b1..30fa434fad 100644
--- a/core/string/node_path.cpp
+++ b/core/string/node_path.cpp
@@ -199,6 +199,21 @@ Vector<StringName> NodePath::get_subnames() const {
return Vector<StringName>();
}
+StringName NodePath::get_concatenated_names() const {
+ ERR_FAIL_COND_V(!data, StringName());
+
+ if (!data->concatenated_path) {
+ int pc = data->path.size();
+ String concatenated;
+ const StringName *sn = data->path.ptr();
+ for (int i = 0; i < pc; i++) {
+ concatenated += i == 0 ? sn[i].operator String() : "/" + sn[i];
+ }
+ data->concatenated_path = concatenated;
+ }
+ return data->concatenated_path;
+}
+
StringName NodePath::get_concatenated_subnames() const {
ERR_FAIL_COND_V(!data, StringName());
diff --git a/core/string/node_path.h b/core/string/node_path.h
index 53976bd524..2bce33e21e 100644
--- a/core/string/node_path.h
+++ b/core/string/node_path.h
@@ -39,6 +39,7 @@ class NodePath {
SafeRefCount refcount;
Vector<StringName> path;
Vector<StringName> subpath;
+ StringName concatenated_path;
StringName concatenated_subpath;
bool absolute;
bool has_slashes;
@@ -59,6 +60,7 @@ public:
StringName get_subname(int p_idx) const;
Vector<StringName> get_names() const;
Vector<StringName> get_subnames() const;
+ StringName get_concatenated_names() const;
StringName get_concatenated_subnames() const;
NodePath rel_path_to(const NodePath &p_np) const;
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index df1aae5370..beefe54faf 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -323,7 +323,13 @@ void String::copy_from(const char *p_cstr) {
char32_t *dst = this->ptrw();
for (size_t i = 0; i <= len; i++) {
- dst[i] = p_cstr[i];
+ uint8_t c = p_cstr[i] >= 0 ? p_cstr[i] : uint8_t(256 + p_cstr[i]);
+ if (c == 0 && i < len) {
+ print_unicode_error("NUL character", true);
+ dst[i] = 0x20;
+ } else {
+ dst[i] = c;
+ }
}
}
@@ -350,7 +356,13 @@ void String::copy_from(const char *p_cstr, const int p_clip_to) {
char32_t *dst = this->ptrw();
for (int i = 0; i < len; i++) {
- dst[i] = p_cstr[i];
+ uint8_t c = p_cstr[i] >= 0 ? p_cstr[i] : uint8_t(256 + p_cstr[i]);
+ if (c == 0) {
+ print_unicode_error("NUL character", true);
+ dst[i] = 0x20;
+ } else {
+ dst[i] = c;
+ }
}
dst[len] = 0;
}
@@ -376,14 +388,21 @@ void String::copy_from(const wchar_t *p_cstr, const int p_clip_to) {
}
void String::copy_from(const char32_t &p_char) {
+ if (p_char == 0) {
+ print_unicode_error("NUL character", true);
+ return;
+ }
+ if ((p_char & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char));
+ }
+ if (p_char > 0x10ffff) {
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char));
+ }
+
resize(2);
+
char32_t *dst = ptrw();
- if ((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff)) {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char, 16) + ".");
- dst[0] = 0xfffd;
- } else {
- dst[0] = p_char;
- }
+ dst[0] = p_char;
dst[1] = 0;
}
@@ -437,12 +456,18 @@ void String::copy_from_unchecked(const char32_t *p_char, const int p_length) {
dst[p_length] = 0;
for (int i = 0; i < p_length; i++) {
- if ((p_char[i] >= 0xd800 && p_char[i] <= 0xdfff) || (p_char[i] > 0x10ffff)) {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char[i], 16) + ".");
- dst[i] = 0xfffd;
- } else {
- dst[i] = p_char[i];
+ if (p_char[i] == 0) {
+ print_unicode_error("NUL character", true);
+ dst[i] = 0x20;
+ continue;
+ }
+ if ((p_char[i] & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char[i]));
}
+ if (p_char[i] > 0x10ffff) {
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char[i]));
+ }
+ dst[i] = p_char[i];
}
}
@@ -481,7 +506,7 @@ String operator+(const wchar_t *p_chr, const String &p_str) {
// wchar_t is 16-bit
String tmp = String::utf16((const char16_t *)p_chr);
#else
- // wchar_t is 32-bi
+ // wchar_t is 32-bit
String tmp = (const char32_t *)p_chr;
#endif
tmp += p_str;
@@ -527,7 +552,13 @@ String &String::operator+=(const char *p_str) {
char32_t *dst = ptrw() + lhs_len;
for (size_t i = 0; i <= rhs_len; i++) {
- dst[i] = p_str[i];
+ uint8_t c = p_str[i] >= 0 ? p_str[i] : uint8_t(256 + p_str[i]);
+ if (c == 0 && i < rhs_len) {
+ print_unicode_error("NUL character", true);
+ dst[i] = 0x20;
+ } else {
+ dst[i] = c;
+ }
}
return *this;
@@ -550,15 +581,21 @@ String &String::operator+=(const char32_t *p_str) {
}
String &String::operator+=(char32_t p_char) {
+ if (p_char == 0) {
+ print_unicode_error("NUL character", true);
+ return *this;
+ }
+ if ((p_char & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)p_char));
+ }
+ if (p_char > 0x10ffff) {
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)p_char));
+ }
+
const int lhs_len = length();
resize(lhs_len + 2);
char32_t *dst = ptrw();
- if ((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff)) {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char, 16) + ".");
- dst[lhs_len] = 0xfffd;
- } else {
- dst[lhs_len] = p_char;
- }
+ dst[lhs_len] = p_char;
dst[lhs_len + 1] = 0;
return *this;
@@ -1583,6 +1620,14 @@ String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) {
return ret;
}
+void String::print_unicode_error(const String &p_message, bool p_critical) const {
+ if (p_critical) {
+ print_error(vformat("Unicode parsing error, some characters were replaced with spaces: %s", p_message));
+ } else {
+ print_error(vformat("Unicode parsing error: %s", p_message));
+ }
+}
+
CharString String::ascii(bool p_allow_extended) const {
if (!length()) {
return CharString();
@@ -1596,7 +1641,7 @@ CharString String::ascii(bool p_allow_extended) const {
if ((c <= 0x7f) || (c <= 0xff && p_allow_extended)) {
cs[i] = c;
} else {
- print_error("Unicode parsing error: Cannot represent " + num_int64(c, 16) + " as ASCII/Latin-1 character.");
+ print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as ASCII/Latin-1", (uint32_t)c));
cs[i] = 0x20;
}
}
@@ -1611,11 +1656,9 @@ String String::utf8(const char *p_utf8, int p_len) {
return ret;
}
-bool String::parse_utf8(const char *p_utf8, int p_len) {
-#define UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?");
-
+Error String::parse_utf8(const char *p_utf8, int p_len) {
if (!p_utf8) {
- return true;
+ return ERR_INVALID_DATA;
}
String aux;
@@ -1635,14 +1678,17 @@ bool String::parse_utf8(const char *p_utf8, int p_len) {
}
}
+ bool decode_error = false;
+ bool decode_failed = false;
{
const char *ptrtmp = p_utf8;
const char *ptrtmp_limit = &p_utf8[p_len];
int skip = 0;
+ uint8_t c_start = 0;
while (ptrtmp != ptrtmp_limit && *ptrtmp) {
- if (skip == 0) {
- uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp);
+ uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp);
+ if (skip == 0) {
/* Determine the number of characters in sequence */
if ((c & 0x80) == 0) {
skip = 0;
@@ -1652,20 +1698,34 @@ bool String::parse_utf8(const char *p_utf8, int p_len) {
skip = 2;
} else if ((c & 0xf8) == 0xf0) {
skip = 3;
+ } else if ((c & 0xfc) == 0xf8) {
+ skip = 4;
+ } else if ((c & 0xfe) == 0xfc) {
+ skip = 5;
} else {
- UNICERROR("invalid skip at " + num_int64(cstr_size));
- return true; //invalid utf8
+ skip = 0;
+ print_unicode_error(vformat("Invalid UTF-8 leading byte (%x)", c), true);
+ decode_failed = true;
}
+ c_start = c;
if (skip == 1 && (c & 0x1e) == 0) {
- UNICERROR("overlong rejected at " + num_int64(cstr_size));
- return true; //reject overlong
+ print_unicode_error(vformat("Overlong encoding (%x ...)", c));
+ decode_error = true;
}
-
str_size++;
-
} else {
- --skip;
+ if ((c_start == 0xe0 && skip == 2 && c < 0xa0) || (c_start == 0xf0 && skip == 3 && c < 0x90) || (c_start == 0xf8 && skip == 4 && c < 0x88) || (c_start == 0xfc && skip == 5 && c < 0x84)) {
+ print_unicode_error(vformat("Overlong encoding (%x %x ...)", c_start, c));
+ decode_error = true;
+ }
+ if (c < 0x80 || c > 0xbf) {
+ print_unicode_error(vformat("Invalid UTF-8 continuation byte (%x ... %x ...)", c_start, c), true);
+ decode_failed = true;
+ skip = 0;
+ } else {
+ --skip;
+ }
}
cstr_size++;
@@ -1673,80 +1733,91 @@ bool String::parse_utf8(const char *p_utf8, int p_len) {
}
if (skip) {
- UNICERROR("no space left");
- return true; //not enough space
+ print_unicode_error(vformat("Missing %d UTF-8 continuation byte(s)", skip), true);
+ decode_failed = true;
}
}
if (str_size == 0) {
clear();
- return false;
+ return OK; // empty string
}
resize(str_size + 1);
char32_t *dst = ptrw();
dst[str_size] = 0;
+ int skip = 0;
+ uint32_t unichar = 0;
while (cstr_size) {
- int len = 0;
-
- /* Determine the number of characters in sequence */
- if ((*p_utf8 & 0x80) == 0) {
- len = 1;
- } else if ((*p_utf8 & 0xe0) == 0xc0) {
- len = 2;
- } else if ((*p_utf8 & 0xf0) == 0xe0) {
- len = 3;
- } else if ((*p_utf8 & 0xf8) == 0xf0) {
- len = 4;
- } else {
- UNICERROR("invalid len");
- return true; //invalid UTF8
- }
-
- if (len > cstr_size) {
- UNICERROR("no space left");
- return true; //not enough space
- }
-
- if (len == 2 && (*p_utf8 & 0x1E) == 0) {
- UNICERROR("no space left");
- return true; //reject overlong
- }
-
- /* Convert the first character */
-
- uint32_t unichar = 0;
-
- if (len == 1) {
- unichar = *p_utf8;
+ uint8_t c = *p_utf8 >= 0 ? *p_utf8 : uint8_t(256 + *p_utf8);
+
+ if (skip == 0) {
+ /* Determine the number of characters in sequence */
+ if ((c & 0x80) == 0) {
+ *(dst++) = c;
+ unichar = 0;
+ skip = 0;
+ } else if ((c & 0xe0) == 0xc0) {
+ unichar = (0xff >> 3) & c;
+ skip = 1;
+ } else if ((c & 0xf0) == 0xe0) {
+ unichar = (0xff >> 4) & c;
+ skip = 2;
+ } else if ((c & 0xf8) == 0xf0) {
+ unichar = (0xff >> 5) & c;
+ skip = 3;
+ } else if ((c & 0xfc) == 0xf8) {
+ unichar = (0xff >> 6) & c;
+ skip = 4;
+ } else if ((c & 0xfe) == 0xfc) {
+ unichar = (0xff >> 7) & c;
+ skip = 5;
+ } else {
+ *(dst++) = 0x20;
+ unichar = 0;
+ skip = 0;
+ }
} else {
- unichar = (0xff >> (len + 1)) & *p_utf8;
-
- for (int i = 1; i < len; i++) {
- if ((p_utf8[i] & 0xc0) != 0x80) {
- UNICERROR("invalid utf8");
- return true; //invalid utf8
- }
- if (unichar == 0 && i == 2 && ((p_utf8[i] & 0x7f) >> (7 - len)) == 0) {
- UNICERROR("invalid utf8 overlong");
- return true; //no overlong
+ if (c < 0x80 || c > 0xbf) {
+ *(dst++) = 0x20;
+ skip = 0;
+ } else {
+ unichar = (unichar << 6) | (c & 0x3f);
+ --skip;
+ if (skip == 0) {
+ if (unichar == 0) {
+ print_unicode_error("NUL character", true);
+ decode_failed = true;
+ unichar = 0x20;
+ }
+ if ((unichar & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", unichar));
+ decode_error = true;
+ }
+ if (unichar > 0x10ffff) {
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", unichar));
+ decode_error = true;
+ }
+ *(dst++) = unichar;
}
- unichar = (unichar << 6) | (p_utf8[i] & 0x3f);
}
}
- if (unichar >= 0xd800 && unichar <= 0xdfff) {
- UNICERROR("invalid code point");
- return CharString();
- }
- *(dst++) = unichar;
- cstr_size -= len;
- p_utf8 += len;
+ cstr_size--;
+ p_utf8++;
+ }
+ if (skip) {
+ *(dst++) = 0x20;
}
- return false;
-#undef UNICERROR
+ if (decode_failed) {
+ return ERR_INVALID_DATA;
+ } else if (decode_error) {
+ return ERR_PARSE_ERROR;
+ } else {
+ return OK;
+ }
}
CharString String::utf8() const {
@@ -1765,15 +1836,17 @@ CharString String::utf8() const {
fl += 2;
} else if (c <= 0xffff) { // 16 bits
fl += 3;
- } else if (c <= 0x0010ffff) { // 21 bits
+ } else if (c <= 0x001fffff) { // 21 bits
fl += 4;
+ } else if (c <= 0x03ffffff) { // 26 bits
+ fl += 5;
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", c));
+ } else if (c <= 0x7fffffff) { // 31 bits
+ fl += 6;
+ print_unicode_error(vformat("Invalid unicode codepoint (%x)", c));
} else {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + ".");
- return CharString();
- }
- if (c >= 0xd800 && c <= 0xdfff) {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + ".");
- return CharString();
+ fl += 1;
+ print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as UTF-8", c), true);
}
}
@@ -1799,11 +1872,26 @@ CharString String::utf8() const {
APPEND_CHAR(uint32_t(0xe0 | ((c >> 12) & 0x0f))); // Top 4 bits.
APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Middle 6 bits.
APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
- } else { // 21 bits
+ } else if (c <= 0x001fffff) { // 21 bits
APPEND_CHAR(uint32_t(0xf0 | ((c >> 18) & 0x07))); // Top 3 bits.
APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper middle 6 bits.
APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits.
APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
+ } else if (c <= 0x03ffffff) { // 26 bits
+ APPEND_CHAR(uint32_t(0xf8 | ((c >> 24) & 0x03))); // Top 2 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Upper middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
+ } else if (c <= 0x7fffffff) { // 31 bits
+ APPEND_CHAR(uint32_t(0xfc | ((c >> 30) & 0x01))); // Top 1 bit.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 24) & 0x3f))); // Upper upper middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Lower upper middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper lower middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower lower middle 6 bits.
+ APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits.
+ } else {
+ APPEND_CHAR(0x20);
}
}
#undef APPEND_CHAR
@@ -1819,11 +1907,9 @@ String String::utf16(const char16_t *p_utf16, int p_len) {
return ret;
}
-bool String::parse_utf16(const char16_t *p_utf16, int p_len) {
-#define UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-16?");
-
+Error String::parse_utf16(const char16_t *p_utf16, int p_len) {
if (!p_utf16) {
- return true;
+ return ERR_INVALID_DATA;
}
String aux;
@@ -1850,80 +1936,90 @@ bool String::parse_utf16(const char16_t *p_utf16, int p_len) {
}
}
+ bool decode_error = false;
{
const char16_t *ptrtmp = p_utf16;
const char16_t *ptrtmp_limit = &p_utf16[p_len];
- int skip = 0;
+ uint32_t c_prev = 0;
+ bool skip = false;
while (ptrtmp != ptrtmp_limit && *ptrtmp) {
uint32_t c = (byteswap) ? BSWAP16(*ptrtmp) : *ptrtmp;
- if (skip == 0) {
- if ((c & 0xfffffc00) == 0xd800) {
- skip = 1; // lead surrogate
- } else if ((c & 0xfffffc00) == 0xdc00) {
- UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size));
- return true; // invalid UTF16
- } else {
- skip = 0;
+
+ if ((c & 0xfffffc00) == 0xd800) { // lead surrogate
+ if (skip) {
+ print_unicode_error(vformat("Unpaired lead surrogate (%x [trail?] %x)", c_prev, c));
+ decode_error = true;
}
- str_size++;
- } else {
- if ((c & 0xfffffc00) == 0xdc00) { // trail surrogate
- --skip;
+ skip = true;
+ } else if ((c & 0xfffffc00) == 0xdc00) { // trail surrogate
+ if (skip) {
+ str_size--;
} else {
- UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size));
- return true; // invalid UTF16
+ print_unicode_error(vformat("Unpaired trail surrogate (%x [lead?] %x)", c_prev, c));
+ decode_error = true;
}
+ skip = false;
+ } else {
+ skip = false;
}
+ c_prev = c;
+ str_size++;
cstr_size++;
ptrtmp++;
}
if (skip) {
- UNICERROR("no space left");
- return true; // not enough space
+ print_unicode_error(vformat("Unpaired lead surrogate (%x [eol])", c_prev));
+ decode_error = true;
}
}
if (str_size == 0) {
clear();
- return false;
+ return OK; // empty string
}
resize(str_size + 1);
char32_t *dst = ptrw();
dst[str_size] = 0;
+ bool skip = false;
+ uint32_t c_prev = 0;
while (cstr_size) {
- int len = 0;
uint32_t c = (byteswap) ? BSWAP16(*p_utf16) : *p_utf16;
- if ((c & 0xfffffc00) == 0xd800) {
- len = 2;
+ if ((c & 0xfffffc00) == 0xd800) { // lead surrogate
+ if (skip) {
+ *(dst++) = c_prev; // unpaired, store as is
+ }
+ skip = true;
+ } else if ((c & 0xfffffc00) == 0xdc00) { // trail surrogate
+ if (skip) {
+ *(dst++) = (c_prev << 10UL) + c - ((0xd800 << 10UL) + 0xdc00 - 0x10000); // decode pair
+ } else {
+ *(dst++) = c; // unpaired, store as is
+ }
+ skip = false;
} else {
- len = 1;
+ *(dst++) = c;
+ skip = false;
}
- if (len > cstr_size) {
- UNICERROR("no space left");
- return true; //not enough space
- }
-
- uint32_t unichar = 0;
- if (len == 1) {
- unichar = c;
- } else {
- uint32_t c2 = (byteswap) ? BSWAP16(p_utf16[1]) : p_utf16[1];
- unichar = (c << 10UL) + c2 - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
- }
+ cstr_size--;
+ p_utf16++;
+ c_prev = c;
+ }
- *(dst++) = unichar;
- cstr_size -= len;
- p_utf16 += len;
+ if (skip) {
+ *(dst++) = c_prev;
}
- return false;
-#undef UNICERROR
+ if (decode_error) {
+ return ERR_PARSE_ERROR;
+ } else {
+ return OK;
+ }
}
Char16String String::utf16() const {
@@ -1938,15 +2034,14 @@ Char16String String::utf16() const {
uint32_t c = d[i];
if (c <= 0xffff) { // 16 bits.
fl += 1;
+ if ((c & 0xfffff800) == 0xd800) {
+ print_unicode_error(vformat("Unpaired surrogate (%x)", c));
+ }
} else if (c <= 0x10ffff) { // 32 bits.
fl += 2;
} else {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + ".");
- return Char16String();
- }
- if (c >= 0xd800 && c <= 0xdfff) {
- print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + ".");
- return Char16String();
+ print_unicode_error(vformat("Invalid unicode codepoint (%x), cannot represent as UTF-16", c), true);
+ fl += 1;
}
}
@@ -1965,9 +2060,11 @@ Char16String String::utf16() const {
if (c <= 0xffff) { // 16 bits.
APPEND_CHAR(c);
- } else { // 32 bits.
+ } else if (c <= 0x10ffff) { // 32 bits.
APPEND_CHAR(uint32_t((c >> 10) + 0xd7c0)); // lead surrogate.
APPEND_CHAR(uint32_t((c & 0x3ff) | 0xdc00)); // trail surrogate.
+ } else {
+ APPEND_CHAR(0x20);
}
}
#undef APPEND_CHAR
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 11d0974381..1b8bf3d234 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -271,6 +271,9 @@ public:
bool is_valid_string() const;
+ /* debug, error messages */
+ void print_unicode_error(const String &p_message, bool p_critical = false) const;
+
/* complex helpers */
String substr(int p_from, int p_chars = -1) const;
int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed
@@ -373,11 +376,11 @@ public:
CharString ascii(bool p_allow_extended = false) const;
CharString utf8() const;
- bool parse_utf8(const char *p_utf8, int p_len = -1); //return true on error
+ Error parse_utf8(const char *p_utf8, int p_len = -1);
static String utf8(const char *p_utf8, int p_len = -1);
Char16String utf16() const;
- bool parse_utf16(const char16_t *p_utf16, int p_len = -1); //return true on error
+ Error parse_utf16(const char16_t *p_utf16, int p_len = -1);
static String utf16(const char16_t *p_utf16, int p_len = -1);
static uint32_t hash(const char32_t *p_cstr, int p_len); /* hash the string */
diff --git a/core/templates/lru.h b/core/templates/lru.h
index 48ba318b12..b08b6455b6 100644
--- a/core/templates/lru.h
+++ b/core/templates/lru.h
@@ -35,7 +35,7 @@
#include "hash_map.h"
#include "list.h"
-template <class TKey, class TData>
+template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>>
class LRUCache {
private:
struct Pair {
@@ -52,7 +52,7 @@ private:
typedef typename List<Pair>::Element *Element;
List<Pair> _list;
- HashMap<TKey, Element> _map;
+ HashMap<TKey, Element, Hasher, Comparator> _map;
size_t capacity;
public:
@@ -102,6 +102,7 @@ public:
}
_FORCE_INLINE_ size_t get_capacity() const { return capacity; }
+ _FORCE_INLINE_ size_t get_size() const { return _map.size(); }
void set_capacity(size_t p_capacity) {
if (capacity > 0) {
diff --git a/core/templates/vector.h b/core/templates/vector.h
index 2ac7c7630a..f3f5ed76a7 100644
--- a/core/templates/vector.h
+++ b/core/templates/vector.h
@@ -145,6 +145,9 @@ public:
Vector<uint8_t> to_byte_array() const {
Vector<uint8_t> ret;
+ if (is_empty()) {
+ return ret;
+ }
ret.resize(size() * sizeof(T));
memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
return ret;
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 22a13b0fab..84f894dcbf 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -106,6 +106,29 @@ struct VariantCaster<const T &> {
static void initialize(m_enum &value) { value = (m_enum)0; } \
};
+#define VARIANT_BITFIELD_CAST(m_enum) \
+ MAKE_BITFIELD_TYPE_INFO(m_enum) \
+ template <> \
+ struct VariantCaster<BitField<m_enum>> { \
+ static _FORCE_INLINE_ BitField<m_enum> cast(const Variant &p_variant) { \
+ return BitField<m_enum>(p_variant.operator int64_t()); \
+ } \
+ }; \
+ template <> \
+ struct PtrToArg<BitField<m_enum>> { \
+ _FORCE_INLINE_ static BitField<m_enum> convert(const void *p_ptr) { \
+ return BitField<m_enum>(*reinterpret_cast<const int64_t *>(p_ptr)); \
+ } \
+ typedef int64_t EncodeT; \
+ _FORCE_INLINE_ static void encode(BitField<m_enum> p_val, const void *p_ptr) { \
+ *(int64_t *)p_ptr = p_val; \
+ } \
+ }; \
+ template <> \
+ struct ZeroInitializer<BitField<m_enum>> { \
+ static void initialize(BitField<m_enum> &value) { value = 0; } \
+ };
+
// Object enum casts must go here
VARIANT_ENUM_CAST(Object::ConnectFlags);
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index bacd0d19ce..794274dd77 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -279,6 +279,51 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) {
return GetTypeInfo<T>::get_class_info().class_name;
}
+template <class T>
+class BitField {
+ uint32_t value = 0;
+
+public:
+ _FORCE_INLINE_ void set_flag(T p_flag) { value |= p_flag; }
+ _FORCE_INLINE_ bool has_flag(T p_flag) const { return value & p_flag; }
+ _FORCE_INLINE_ void clear_flag(T p_flag) { return value &= ~p_flag; }
+ _FORCE_INLINE_ BitField(uint32_t p_value) { value = p_value; }
+ _FORCE_INLINE_ operator uint32_t() const { return value; }
+};
+
+#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
+ template <> \
+ struct GetTypeInfo<m_impl> { \
+ static const Variant::Type VARIANT_TYPE = Variant::INT; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
+ godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<BitField<m_impl>> { \
+ static const Variant::Type VARIANT_TYPE = Variant::INT; \
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_BITFIELD, \
+ godot::details::enum_qualified_name_to_class_info_name(String(#m_enum))); \
+ } \
+ };
+
+#define MAKE_BITFIELD_TYPE_INFO(m_enum) \
+ TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum) \
+ TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum const) \
+ TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_enum &) \
+ TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, const m_enum &)
+
+template <typename T>
+inline StringName __constant_get_bitfield_name(T param, const String &p_constant) {
+ if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) {
+ ERR_PRINT("Missing VARIANT_ENUM_CAST for constant's bitfield: " + p_constant);
+ }
+ return GetTypeInfo<BitField<T>>::get_class_info().class_name;
+}
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
template <typename T>
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index a4bb7630d6..8e16a767cf 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -753,40 +753,56 @@ struct _VariantCall {
static PackedInt32Array func_PackedByteArray_decode_s32_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
PackedInt32Array dest;
- ERR_FAIL_COND_V_MSG(size < sizeof(int32_t), dest, "Size didn't match array of size int32_t, maybe you are trying to convert to the wrong type?");
+ if (size == 0) {
+ return dest;
+ }
+ ERR_FAIL_COND_V_MSG(size % sizeof(int32_t), dest, "PackedByteArray size must be a multiple of 4 (size of 32-bit integer) to convert to PackedInt32Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int32_t));
- memcpy(dest.ptrw(), r, size);
+ ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ memcpy(dest.ptrw(), r, dest.size() * sizeof(int32_t));
return dest;
}
static PackedInt64Array func_PackedByteArray_decode_s64_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
PackedInt64Array dest;
- ERR_FAIL_COND_V_MSG(size < sizeof(int64_t), dest, "Size didn't match array of size int64_t, maybe you are trying to convert to the wrong type?");
+ if (size == 0) {
+ return dest;
+ }
+ ERR_FAIL_COND_V_MSG(size % sizeof(int64_t), dest, "PackedByteArray size must be a multiple of 8 (size of 64-bit integer) to convert to PackedInt64Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(int64_t));
- memcpy(dest.ptrw(), r, size);
+ ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ memcpy(dest.ptrw(), r, dest.size() * sizeof(int64_t));
return dest;
}
static PackedFloat32Array func_PackedByteArray_decode_float_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
PackedFloat32Array dest;
- ERR_FAIL_COND_V_MSG(size < sizeof(float), dest, "Size didn't match array of size float, maybe you are trying to convert to the wrong type?");
+ if (size == 0) {
+ return dest;
+ }
+ ERR_FAIL_COND_V_MSG(size % sizeof(float), dest, "PackedByteArray size must be a multiple of 4 (size of 32-bit float) to convert to PackedFloat32Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(float));
- memcpy(dest.ptrw(), r, size);
+ ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ memcpy(dest.ptrw(), r, dest.size() * sizeof(float));
return dest;
}
static PackedFloat64Array func_PackedByteArray_decode_double_array(PackedByteArray *p_instance) {
uint64_t size = p_instance->size();
PackedFloat64Array dest;
- ERR_FAIL_COND_V_MSG(size < sizeof(double), dest, "Size didn't match array of size double, maybe you are trying to convert to the wrong type?");
+ if (size == 0) {
+ return dest;
+ }
+ ERR_FAIL_COND_V_MSG(size % sizeof(double), dest, "PackedByteArray size must be a multiple of 8 (size of 64-bit double) to convert to PackedFloat64Array.");
const uint8_t *r = p_instance->ptr();
dest.resize(size / sizeof(double));
- memcpy(dest.ptrw(), r, size);
+ ERR_FAIL_COND_V(dest.size() == 0, dest); // Avoid UB in case resize failed.
+ memcpy(dest.ptrw(), r, dest.size() * sizeof(double));
return dest;
}
@@ -1790,6 +1806,7 @@ static void _register_variant_builtin_methods() {
bind_method(NodePath, get_subname_count, sarray(), varray());
bind_method(NodePath, hash, sarray(), varray());
bind_method(NodePath, get_subname, sarray("idx"), varray());
+ bind_method(NodePath, get_concatenated_names, sarray(), varray());
bind_method(NodePath, get_concatenated_subnames, sarray(), varray());
bind_method(NodePath, get_as_property_path, sarray(), varray());
bind_method(NodePath, is_empty, sarray(), varray());
diff --git a/doc/class.xsd b/doc/class.xsd
index 498c930d6f..70c0323464 100644
--- a/doc/class.xsd
+++ b/doc/class.xsd
@@ -155,6 +155,7 @@
<xs:attribute type="xs:string" name="name" />
<xs:attribute type="xs:string" name="value" />
<xs:attribute type="xs:string" name="enum" use="optional" />
+ <xs:attribute type="xs:boolean" name="is_bitfield" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
@@ -162,6 +163,42 @@
</xs:sequence>
</xs:complexType>
</xs:element>
+ <xs:element name="annotations" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="annotation" maxOccurs="unbounded" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="return" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:sequence />
+ </xs:sequence>
+ <xs:attribute type="xs:string" name="type" />
+ <xs:attribute type="xs:string" name="enum" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="argument" maxOccurs="unbounded" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:sequence />
+ </xs:sequence>
+ <xs:attribute type="xs:byte" name="index" />
+ <xs:attribute type="xs:string" name="name" />
+ <xs:attribute type="xs:string" name="type" />
+ <xs:attribute type="xs:string" name="enum" use="optional" />
+ <xs:attribute type="xs:string" name="default" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element type="xs:string" name="description" />
+ </xs:sequence>
+ <xs:attribute type="xs:string" name="name" use="optional" />
+ <xs:attribute type="xs:string" name="qualifiers" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
<xs:element name="theme_items" minOccurs="0">
<xs:complexType>
<xs:sequence>
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index 26fe1278f7..e0bc98e208 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -55,6 +55,7 @@
</member>
<member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Bus on which this audio is playing.
+ [b]Note:[/b] When setting this property, keep in mind that no validation is performed to see if the given name matches an existing bus. This is because audio bus layouts might be loaded after this property is set. If this given name can't be resolved at runtime, it will fall back to [code]"Master"[/code].
</member>
<member name="max_polyphony" type="int" setter="set_max_polyphony" getter="get_max_polyphony" default="1">
The maximum number of sounds this node can play at the same time. Playing additional sounds after this value is reached will cut off the oldest sounds.
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index 76666b1f27..f04f95bd72 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -57,6 +57,7 @@
</member>
<member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Bus on which this audio is playing.
+ [b]Note:[/b] When setting this property, keep in mind that no validation is performed to see if the given name matches an existing bus. This is because audio bus layouts might be loaded after this property is set. If this given name can't be resolved at runtime, it will fall back to [code]"Master"[/code].
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="2000.0">
Maximum distance from which audio is still hearable.
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index a49b1e2291..72febf7006 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -64,6 +64,7 @@
</member>
<member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
The bus on which this audio is playing.
+ [b]Note:[/b] When setting this property, keep in mind that no validation is performed to see if the given name matches an existing bus. This is because audio bus layouts might be loaded after this property is set. If this given name can't be resolved at runtime, it will fall back to [code]"Master"[/code].
</member>
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking" default="0">
Decides in which step the Doppler effect should be calculated.
diff --git a/doc/classes/BoneMap.xml b/doc/classes/BoneMap.xml
new file mode 100644
index 0000000000..371cb4fa93
--- /dev/null
+++ b/doc/classes/BoneMap.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="BoneMap" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Bone map for retargeting.
+ </brief_description>
+ <description>
+ This class contains a hashmap that uses a list of bone names in [SkeletonProfile] as key names.
+ By assigning the actual [Skeleton3D] bone name as the key value, it maps the [Skeleton3D] to the [SkeletonProfile].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="find_profile_bone_name" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="skeleton_bone_name" type="StringName" />
+ <description>
+ Returns a profile bone name having [code]skeleton_bone_name[/code]. If not found, an empty [StringName] will be returned.
+ In the retargeting process, the returned bone name is the bone name of the target skeleton.
+ </description>
+ </method>
+ <method name="get_skeleton_bone_name" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="profile_bone_name" type="StringName" />
+ <description>
+ Returns a skeleton bone name is mapped to [code]profile_bone_name[/code].
+ In the retargeting process, the returned bone name is the bone name of the source skeleton.
+ </description>
+ </method>
+ <method name="set_skeleton_bone_name">
+ <return type="void" />
+ <argument index="0" name="profile_bone_name" type="StringName" />
+ <argument index="1" name="skeleton_bone_name" type="StringName" />
+ <description>
+ Maps a skeleton bone name to [code]profile_bone_name[/code].
+ In the retargeting process, the setting bone name is the bone name of the source skeleton.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="profile" type="SkeletonProfile" setter="set_profile" getter="get_profile">
+ A [SkeletonProfile] of the mapping target. Key names in the [BoneMap] are synchronized with it.
+ </member>
+ </members>
+ <signals>
+ <signal name="bone_map_updated">
+ <description>
+ This signal is emitted when change the key value in the [BoneMap]. This is used to validate mapping and to update [BoneMap] editor.
+ </description>
+ </signal>
+ <signal name="profile_updated">
+ <description>
+ This signal is emitted when change the value in profile or change the reference of profile. This is used to update key names in the [BoneMap] and to redraw the [BoneMap] editor.
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml
index 1e0b685795..1cd9ca0afb 100644
--- a/doc/classes/Button.xml
+++ b/doc/classes/Button.xml
@@ -40,29 +40,6 @@
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
- <methods>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
- </methods>
<members>
<member name="alignment" type="int" setter="set_text_alignment" getter="get_text_alignment" enum="HorizontalAlignment" default="1">
Text alignment policy for the button's text, use one of the [enum @GlobalScope.HorizontalAlignment] constants.
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 98a498d719..acf08414d0 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -48,17 +48,26 @@
</description>
</method>
<method name="draw_char" qualifiers="const">
- <return type="float" />
+ <return type="void" />
+ <argument index="0" name="font" type="Font" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="char" type="String" />
+ <argument index="3" name="font_size" type="int" default="16" />
+ <argument index="4" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
+ <description>
+ Draws a string first character using a custom font.
+ </description>
+ </method>
+ <method name="draw_char_outline" qualifiers="const">
+ <return type="void" />
<argument index="0" name="font" type="Font" />
<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="16" />
+ <argument index="3" name="font_size" type="int" default="16" />
+ <argument index="4" name="size" type="int" default="-1" />
<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)" />
<description>
- Draws a string character using a custom font. Returns the advance, depending on the character width and kerning with an optional next character.
+ Draws a string first character outline using a custom font.
</description>
</method>
<method name="draw_circle">
@@ -127,7 +136,7 @@
<argument index="4" name="outline" type="float" default="0.0" />
<argument index="5" name="pixel_range" type="float" default="4.0" />
<description>
- Draws a textured rectangle region of the multi-channel signed distance field texture at a given position, optionally modulated by a color. See [member FontData.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
+ Draws a textured rectangle region of the multi-channel signed distance field texture at a given position, optionally modulated by a color. See [member FontFile.multichannel_signed_distance_field] for more information and caveats about MSDF font rendering.
If [code]outline[/code] is positive, each alpha channel value of pixel in region is set to maximum value of true distance in the [code]outline[/code] radius.
Value of the [code]pixel_range[/code] should the same that was used during distance field texture generation.
</description>
@@ -157,16 +166,34 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" 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="16" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="max_lines" type="int" default="-1" />
<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)" />
- <argument index="10" name="flags" type="int" default="99" />
+ <argument index="8" name="flags" type="int" default="99" />
+ <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines and draws it using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
</description>
</method>
+ <method name="draw_multiline_string_outline" qualifiers="const">
+ <return type="void" />
+ <argument index="0" name="font" type="Font" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="text" type="String" />
+ <argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="4" name="width" type="float" default="-1" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="max_lines" type="int" default="-1" />
+ <argument index="7" name="size" type="int" default="1" />
+ <argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
+ <argument index="9" name="flags" type="int" default="99" />
+ <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
+ <description>
+ Breaks [code]text[/code] to the lines and draws text outline using the specified [code]font[/code] at the [code]position[/code] (top-left corner). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
+ </description>
+ </method>
<method name="draw_multimesh">
<return type="void" />
<argument index="0" name="multimesh" type="MultiMesh" />
@@ -250,11 +277,11 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
- <argument index="5" name="size" type="int" default="16" />
+ <argument index="5" name="font_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)" />
- <argument index="9" name="flags" type="int" default="3" />
+ <argument index="7" name="flags" type="int" default="3" />
+ <argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draws [code]text[/code] using the specified [code]font[/code] at the [code]position[/code] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
[b]Example using the default project font:[/b]
@@ -279,6 +306,23 @@
See also [method Font.draw_string].
</description>
</method>
+ <method name="draw_string_outline" qualifiers="const">
+ <return type="void" />
+ <argument index="0" name="font" type="Font" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="text" type="String" />
+ <argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="4" name="width" type="float" default="-1" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="size" type="int" default="1" />
+ <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
+ <argument index="8" name="flags" type="int" default="3" />
+ <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
+ <description>
+ Draws [code]text[/code] outline using the specified [code]font[/code] at the [code]position[/code] (bottom-left corner using the baseline of the font). The text will have its color multiplied by [code]modulate[/code]. If [code]clip_w[/code] is greater than or equal to 0, the text will be clipped if it exceeds the specified width.
+ </description>
+ </method>
<method name="draw_style_box">
<return type="void" />
<argument index="0" name="style_box" type="StyleBox" />
diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml
index 7ca27a35fe..4994ef352e 100644
--- a/doc/classes/CodeEdit.xml
+++ b/doc/classes/CodeEdit.xml
@@ -592,6 +592,9 @@
<theme_item name="completion_scroll_color" data_type="color" type="Color" default="Color(1, 1, 1, 0.29)">
[Color] of the scrollbar in the code completion popup.
</theme_item>
+ <theme_item name="completion_scroll_hovered_color" data_type="color" type="Color" default="Color(1, 1, 1, 0.4)">
+ [Color] of the scrollbar in the code completion popup when hovered.
+ </theme_item>
<theme_item name="completion_selected_color" data_type="color" type="Color" default="Color(0.26, 0.26, 0.27, 1)">
Background highlight [Color] for the current selected option item in the code completion popup.
</theme_item>
diff --git a/doc/classes/ColorPicker.xml b/doc/classes/ColorPicker.xml
index 7c9c4ed4d6..cc9c5877c5 100644
--- a/doc/classes/ColorPicker.xml
+++ b/doc/classes/ColorPicker.xml
@@ -37,16 +37,15 @@
<member name="color" type="Color" setter="set_pick_color" getter="get_pick_color" default="Color(1, 1, 1, 1)">
The currently selected color.
</member>
+ <member name="color_mode" type="int" setter="set_color_mode" getter="get_color_mode" enum="ColorPicker.ColorModeType" default="0">
+ The currently selected color mode. See [enum ColorModeType].
+ </member>
<member name="deferred_mode" type="bool" setter="set_deferred_mode" getter="is_deferred_mode" default="false">
If [code]true[/code], the color will apply only after the user releases the mouse button, otherwise it will apply immediately even in mouse motion event (which can cause performance issues).
</member>
<member name="edit_alpha" type="bool" setter="set_edit_alpha" getter="is_editing_alpha" default="true">
If [code]true[/code], shows an alpha channel slider (opacity).
</member>
- <member name="hsv_mode" type="bool" setter="set_hsv_mode" getter="is_hsv_mode" default="false">
- If [code]true[/code], allows editing the color with Hue/Saturation/Value sliders.
- [b]Note:[/b] Cannot be enabled if raw mode is on.
- </member>
<member name="picker_shape" type="int" setter="set_picker_shape" getter="get_picker_shape" enum="ColorPicker.PickerShapeType" default="0">
The shape of the color space view. See [enum PickerShapeType].
</member>
@@ -56,10 +55,6 @@
<member name="presets_visible" type="bool" setter="set_presets_visible" getter="are_presets_visible" default="true">
If [code]true[/code], saved color presets are visible.
</member>
- <member name="raw_mode" type="bool" setter="set_raw_mode" getter="is_raw_mode" default="false">
- If [code]true[/code], allows the color R, G, B component values to go beyond 1.0, which can be used for certain special operations that require it (like tinting without darkening or rendering sprites in HDR).
- [b]Note:[/b] Cannot be enabled if HSV mode is on.
- </member>
</members>
<signals>
<signal name="color_changed">
@@ -82,6 +77,20 @@
</signal>
</signals>
<constants>
+ <constant name="MODE_RGB" value="0" enum="ColorModeType">
+ Allows editing the color with Red/Green/Blue sliders.
+ </constant>
+ <constant name="MODE_HSV" value="1" enum="ColorModeType">
+ Allows editing the color with Hue/Saturation/Value sliders.
+ </constant>
+ <constant name="MODE_RAW" value="2" enum="ColorModeType">
+ Allows the color R, G, B component values to go beyond 1.0, which can be used for certain special operations that require it (like tinting without darkening or rendering sprites in HDR).
+ </constant>
+ <constant name="MODE_OKHSL" value="3" enum="ColorModeType">
+ Allows editing the color with Hue/Saturation/Lightness sliders.
+ OKHSL is a new color space similar to HSL but that better match perception by leveraging the Oklab color space which is designed to be simple to use, while doing a good job at predicting perceived lightness, chroma and hue.
+ [url=https://bottosson.github.io/posts/colorpicker/]Okhsv and Okhsl color spaces[/url]
+ </constant>
<constant name="SHAPE_HSV_RECTANGLE" value="0" enum="PickerShapeType">
HSV Color Model rectangle color space.
</constant>
diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml
index c0ad61b77e..861b4b480c 100644
--- a/doc/classes/Decal.xml
+++ b/doc/classes/Decal.xml
@@ -79,7 +79,7 @@
Sets the size of the [AABB] used by the decal. The AABB goes from [code]-extents[/code] to [code]extents[/code].
</member>
<member name="lower_fade" type="float" setter="set_lower_fade" getter="get_lower_fade" default="0.3">
- Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB].
+ Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]).
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)">
Changes the [Color] of the Decal by multiplying it with this value.
@@ -89,18 +89,22 @@
</member>
<member name="texture_albedo" type="Texture2D" setter="set_texture" getter="get_texture">
[Texture2D] with the base [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object.
+ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="texture_emission" type="Texture2D" setter="set_texture" getter="get_texture">
[Texture2D] with the emission [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object.
+ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="texture_normal" type="Texture2D" setter="set_texture" getter="get_texture">
[Texture2D] with the per-pixel normal map for the decal. Use this to add extra detail to decals.
+ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="texture_orm" type="Texture2D" setter="set_texture" getter="get_texture">
[Texture2D] storing ambient occlusion, roughness, and metallic for the decal. Use this to add extra detail to decals.
+ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter].
</member>
<member name="upper_fade" type="float" setter="set_upper_fade" getter="get_upper_fade" default="0.3">
- Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB].
+ Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]).
</member>
</members>
<constants>
diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml
index 0fdbd5db1e..93fd5e46ba 100644
--- a/doc/classes/EditorScenePostImportPlugin.xml
+++ b/doc/classes/EditorScenePostImportPlugin.xml
@@ -114,7 +114,9 @@
</constant>
<constant name="INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE" value="5" enum="InternalImportCategory">
</constant>
- <constant name="INTERNAL_IMPORT_CATEGORY_MAX" value="6" enum="InternalImportCategory">
+ <constant name="INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE" value="6" enum="InternalImportCategory">
+ </constant>
+ <constant name="INTERNAL_IMPORT_CATEGORY_MAX" value="7" enum="InternalImportCategory">
</constant>
</constants>
</class>
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 9d55704604..903f36d0ce 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -75,6 +75,9 @@
<member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title" default="true">
If [code]true[/code], changing the [code]Mode[/code] property will set the window title accordingly (e.g. setting mode to [constant FILE_MODE_OPEN_FILE] will change the window title to "Open a File").
</member>
+ <member name="root_subfolder" type="String" setter="set_root_subfolder" getter="get_root_subfolder" default="&quot;&quot;">
+ If non-empty, the given sub-folder will be "root" of this [FileDialog], i.e. user won't be able to go to its parent directory.
+ </member>
<member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files" default="false">
If [code]true[/code], the dialog will show hidden files.
</member>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index dae42ddf34..b19386b398 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -1,93 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Font" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Font class is set of font data sources used to draw text.
+ Base class for fonts and font variations.
</brief_description>
<description>
- Font contains a set of glyphs to represent Unicode characters, as well as the ability to draw it with variable width, ascent, descent and kerning.
- [b]Note:[/b] A character is a symbol that represents an item (letter, digit etc.) in an abstract way.
- [b]Note:[/b] A glyph is a bitmap or shape used to draw a one or more characters in a context-dependent manner. Glyph indices are bound to the specific font data source.
- [b]Note:[/b] If a non of the font data sources contain glyphs for a character used in a string, the character in question will be replaced with a box displaying its hexadecimal code.
- [codeblocks]
- [gdscript]
- var font = Font.new()
- font.add_data(load("res://BarlowCondensed-Bold.ttf"))
- $"Label".set("custom_fonts/font", font)
- $"Label".set("custom_fonts/font_size", 64)
- [/gdscript]
- [csharp]
- var font = new Font();
- font.AddData(ResourceLoader.Load&lt;FontData&gt;("res://BarlowCondensed-Bold.ttf"));
- GetNode("Label").Set("custom_fonts/font", font);
- GetNode("Label").Set("custom_font_sizes/font_size", 64);
- [/csharp]
- [/codeblocks]
- To control font substitution priority use [FontData] language and script support.
- Use language overrides to use same [Font] stack for multiple languages:
- [codeblocks]
- [gdscript]
- # Use Naskh font for Persian and Nastaʼlīq font for Urdu text.
- var font_data_fa = load("res://NotoNaskhArabicUI_Regular.ttf");
- font_data_fa.set_language_support_override("fa", true);
- font_data_fa.set_language_support_override("ur", false);
-
- var font_data_ur = load("res://NotoNastaliqUrdu_Regular.ttf");
- font_data_ur.set_language_support_override("fa", false);
- font_data_ur.set_language_support_override("ur", true);
- [/gdscript]
- [csharp]
- // Use Naskh font for Persian and Nastaʼlīq font for Urdu text.
- var fontDataFA = ResourceLoader.Load&lt;FontData&gt;("res://NotoNaskhArabicUI_Regular.ttf");
- fontDataFA.SetLanguageSupportOverride("fa", true);
- fontDataFA.SetLanguageSupportOverride("ur", false);
-
- var fontDataUR = ResourceLoader.Load&lt;FontData&gt;("res://NotoNastaliqUrdu_Regular.ttf");
- fontDataUR.SetLanguageSupportOverride("fa", false);
- fontDataUR.SetLanguageSupportOverride("ur", true);
- [/csharp]
- [/codeblocks]
- Use script overrides to specify supported scripts for bitmap font or for less common scripts not directly supported by TrueType format:
- [codeblocks]
- [gdscript]
- # Use specified font for Egyptian hieroglyphs.
- var font_data = load("res://unifont.ttf");
- font_data.set_script_support_override("Egyp", true);
- [/gdscript]
- [csharp]
- // Use specified font for Egyptian hieroglyphs.
- var fontData = ResourceLoader.Load&lt;FontData&gt;("res://unifont.ttf");
- fontData.SetScriptSupportOverride("Egyp", true);
- [/csharp]
- [/codeblocks]
+ Font is the abstract base class for font, so it shouldn't be used directly. Other types of fonts inherit from it.
</description>
<tutorials>
</tutorials>
<methods>
- <method name="add_data">
- <return type="void" />
- <argument index="0" name="data" type="FontData" />
- <description>
- Add font data source to the set.
- </description>
- </method>
- <method name="clear_data">
- <return type="void" />
+ <method name="draw_char" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="canvas_item" type="RID" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="char" type="int" />
+ <argument index="3" name="modulate" type="int" />
+ <argument index="4" name="arg4" type="Color" default="Color(1, 1, 1, 1)" />
<description>
- Removes all font data sourcers for the set.
+ Draw a single Unicode character [code]char[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ [b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead.
</description>
</method>
- <method name="draw_char" qualifiers="const">
+ <method name="draw_char_outline" qualifiers="const">
<return type="float" />
<argument index="0" name="canvas_item" type="RID" />
<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="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)" />
+ <argument index="3" name="size" type="int" />
+ <argument index="4" name="modulate" type="int" default="-1" />
+ <argument index="5" name="arg5" type="Color" default="Color(1, 1, 1, 1)" />
<description>
- Draw a single Unicode character [code]char[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color, and optionally kerning if [code]next[/code] is passed. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ Draw a single Unicode character [code]char[/code] outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
[b]Note:[/b] Do not use this function to draw strings character by character, use [method draw_string] or [TextLine] instead.
</description>
</method>
@@ -98,17 +41,36 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" 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="16" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="max_lines" type="int" default="-1" />
<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)" />
- <argument index="10" name="flags" type="int" default="99" />
+ <argument index="8" name="flags" type="int" default="99" />
+ <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws it into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_multiline_string].
</description>
</method>
+ <method name="draw_multiline_string_outline" qualifiers="const">
+ <return type="void" />
+ <argument index="0" name="canvas_item" type="RID" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="text" type="String" />
+ <argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="4" name="width" type="float" default="-1" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="max_lines" type="int" default="-1" />
+ <argument index="7" name="size" type="int" default="1" />
+ <argument index="8" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
+ <argument index="9" name="flags" type="int" default="99" />
+ <argument index="10" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="11" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
+ <description>
+ Breaks [code]text[/code] to the lines using rules specified by [code]flags[/code] and draws text outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline of the first line, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ See also [method CanvasItem.draw_multiline_string_outline].
+ </description>
+ </method>
<method name="draw_string" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
@@ -116,19 +78,47 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
<argument index="4" name="width" type="float" default="-1" />
- <argument index="5" name="size" type="int" default="16" />
+ <argument index="5" name="font_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)" />
- <argument index="9" name="flags" type="int" default="3" />
+ <argument index="7" name="flags" type="int" default="3" />
+ <argument index="8" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="9" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Draw [code]text[/code] into a canvas item using the font, at a given position, with [code]modulate[/code] color, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_string].
</description>
</method>
+ <method name="draw_string_outline" qualifiers="const">
+ <return type="void" />
+ <argument index="0" name="canvas_item" type="RID" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="text" type="String" />
+ <argument index="3" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="4" name="width" type="float" default="-1" />
+ <argument index="5" name="font_size" type="int" default="16" />
+ <argument index="6" name="size" type="int" default="1" />
+ <argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
+ <argument index="8" name="flags" type="int" default="3" />
+ <argument index="9" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="10" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
+ <description>
+ Draw [code]text[/code] outline into a canvas item using the font, at a given position, with [code]modulate[/code] color and [code]size[/code] outline size, optionally clipping the width and aligning horizontally. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ See also [method CanvasItem.draw_string_outline].
+ </description>
+ </method>
+ <method name="find_variation" qualifiers="const">
+ <return type="RID" />
+ <argument index="0" name="variation_coordinates" type="Dictionary" />
+ <argument index="1" name="face_index" type="int" default="0" />
+ <argument index="2" name="strength" type="float" default="0.0" />
+ <argument index="3" name="transform" type="Transform2D" default="Transform2D(1, 0, 0, 1, 0, 0)" />
+ <description>
+ Returns [TextServer] RID of the font cache for specific variation.
+ </description>
+ </method>
<method name="get_ascent" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="16" />
+ <argument index="0" name="font_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).
@@ -137,44 +127,53 @@
<method name="get_char_size" qualifiers="const">
<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="16" />
+ <argument index="1" name="arg1" type="int" />
<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.
</description>
</method>
- <method name="get_data" qualifiers="const">
- <return type="FontData" />
- <argument index="0" name="idx" type="int" />
+ <method name="get_descent" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="font_size" type="int" default="16" />
<description>
- Returns the font data source at index [code]idx[/code]. If the index does not exist, returns [code]null[/code].
+ 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).
</description>
</method>
- <method name="get_data_count" qualifiers="const">
+ <method name="get_face_count" qualifiers="const">
<return type="int" />
<description>
- Returns the number of font data sources.
+ Returns number of faces in the TrueType / OpenType collection.
</description>
</method>
- <method name="get_data_rid" qualifiers="const">
- <return type="RID" />
- <argument index="0" name="idx" type="int" />
+ <method name="get_fallbacks" qualifiers="const">
+ <return type="Font[]" />
<description>
- Returns TextServer RID of the font data resources.
+ Returns array of fallback [Font]s.
</description>
</method>
- <method name="get_descent" qualifiers="const">
- <return type="float" />
- <argument index="0" name="size" type="int" default="16" />
+ <method name="get_font_name" qualifiers="const">
+ <return type="String" />
<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).
+ Returns font family name.
+ </description>
+ </method>
+ <method name="get_font_style" qualifiers="const">
+ <return type="int" />
+ <description>
+ Returns font style flags, see [enum TextServer.FontStyle].
+ </description>
+ </method>
+ <method name="get_font_style_name" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns font style name.
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="16" />
+ <argument index="0" name="font_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).
@@ -183,18 +182,28 @@
<method name="get_multiline_string_size" qualifiers="const">
<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="16" />
- <argument index="3" name="flags" type="int" default="96" />
+ <argument index="1" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="2" name="width" type="float" default="-1" />
+ <argument index="3" name="font_size" type="int" default="16" />
+ <argument index="4" name="max_lines" type="int" default="-1" />
+ <argument index="5" name="flags" type="int" default="96" />
+ <argument index="6" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="7" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Returns the size of a bounding box of a string broken into the lines, taking kerning and advance into account.
See also [method draw_multiline_string].
</description>
</method>
+ <method name="get_opentype_features" qualifiers="const">
+ <return type="Dictionary" />
+ <description>
+ Returns a set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
+ </description>
+ </method>
<method name="get_rids" qualifiers="const">
- <return type="Array" />
+ <return type="RID[]" />
<description>
- Returns [Array] of valid [FontData] [RID]s, which can be passed to the [TextServer] methods.
+ Returns [Array] of valid [Font] [RID]s, which can be passed to the [TextServer] methods.
</description>
</method>
<method name="get_spacing" qualifiers="const">
@@ -207,10 +216,12 @@
<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="16" />
- <argument index="2" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
- <argument index="3" name="width" type="float" default="-1" />
+ <argument index="1" name="alignment" type="int" enum="HorizontalAlignment" default="0" />
+ <argument index="2" name="width" type="float" default="-1" />
+ <argument index="3" name="font_size" type="int" default="16" />
<argument index="4" name="flags" type="int" default="3" />
+ <argument index="5" name="direction" type="int" enum="TextServer.Direction" default="0" />
+ <argument index="6" name="orientation" type="int" enum="TextServer.Orientation" default="0" />
<description>
Returns the size of a bounding box of a string, taking kerning and advance into account.
[b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by [method get_height].
@@ -224,9 +235,22 @@
If a given character is included in more than one font data source, it appears only once in the returned string.
</description>
</method>
+ <method name="get_supported_feature_list" qualifiers="const">
+ <return type="Dictionary" />
+ <description>
+ Returns list of OpenType features supported by font.
+ </description>
+ </method>
+ <method name="get_supported_variation_list" qualifiers="const">
+ <return type="Dictionary" />
+ <description>
+ Returns list of supported [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url], each coordinate is returned as [code]tag: Vector3i(min_value,max_value,default_value)[/code].
+ Font variations allow for continuous change of glyph characteristics along some given design axis, such as weight, width or slant.
+ </description>
+ </method>
<method name="get_underline_position" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="16" />
+ <argument index="0" name="font_size" type="int" default="16" />
<description>
Returns 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.
@@ -234,7 +258,7 @@
</method>
<method name="get_underline_thickness" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="16" />
+ <argument index="0" name="font_size" type="int" default="16" />
<description>
Returns 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.
@@ -247,45 +271,34 @@
Returns [code]true[/code] if a Unicode [code]char[/code] is available in the font.
</description>
</method>
- <method name="remove_data">
- <return type="void" />
- <argument index="0" name="idx" type="int" />
+ <method name="is_language_supported" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="language" type="String" />
<description>
- Removes the font data source at index [code]idx[/code]. If the index does not exist, nothing happens.
+ Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code).
</description>
</method>
- <method name="set_data">
- <return type="void" />
- <argument index="0" name="idx" type="int" />
- <argument index="1" name="data" type="FontData" />
+ <method name="is_script_supported" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="script" type="String" />
<description>
- Sets the font data source at index [code]idx[/code]. If the index does not exist, nothing happens.
+ Returns [code]true[/code], if font supports given script ([url=https://en.wikipedia.org/wiki/ISO_15924]ISO 15924[/url] code).
</description>
</method>
- <method name="set_spacing">
+ <method name="set_cache_capacity">
<return type="void" />
- <argument index="0" name="spacing" type="int" enum="TextServer.SpacingType" />
- <argument index="1" name="value" type="int" />
+ <argument index="0" name="single_line" type="int" />
+ <argument index="1" name="multi_line" type="int" />
<description>
- Sets the spacing for [code]type[/code] (see [enum TextServer.SpacingType]) to [code]value[/code] in pixels (not relative to the font size).
+ Sets LRU cache capacity for [code]draw_*[/code] methods.
</description>
</method>
- <method name="update_changes">
+ <method name="set_fallbacks">
<return type="void" />
+ <argument index="0" name="fallbacks" type="Font[]" />
<description>
- After editing a font (changing data sources, etc.). Call this function to propagate changes to controls that might use it.
+ Sets array of fallback [Font]s.
</description>
</method>
</methods>
- <members>
- <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>
- <member name="spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
- Extra spacing at the top of the line in pixels.
- </member>
- <member name="variation_coordinates" type="Dictionary" setter="set_variation_coordinates" getter="get_variation_coordinates" default="{}">
- Default font [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url].
- </member>
- </members>
</class>
diff --git a/doc/classes/FontData.xml b/doc/classes/FontFile.xml
index d32e7b3a94..98abc87b84 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontFile.xml
@@ -1,13 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="FontData" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+<class name="FontFile" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Font source data and prerendered glyph cache, imported from dynamic or bitmap font.
+ FontFile source data and prerendered glyph cache, imported from dynamic or bitmap font.
+ </brief_description>
+ <description>
+ [FontFile] contains a set of glyphs to represent Unicode characters imported from a font file, as well as a cache of rasterized glyphs, and a set of fallback [Font]s to use.
+ Use [FontVariation] to access specific OpenType variation of the font, create simulated bold / slanted version, and draw lines of text.
+ For more complex text processing, use [FontVariation] in conjunction with [TextLine] or [TextParagraph].
Supported font formats:
- Dynamic font importer: TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2), Type 1 (.pfb, .pfm).
- Bitmap font importer: AngelCode BMFont (.fnt, .font), text and binary (version 3) format variants.
- Monospace image font importer: All supported image formats.
- </brief_description>
- <description>
+ [b]Note:[/b] A character is a symbol that represents an item (letter, digit etc.) in an abstract way.
+ [b]Note:[/b] A glyph is a bitmap or shape used to draw a one or more characters in a context-dependent manner. Glyph indices are bound to the specific font data source.
+ [b]Note:[/b] If a none of the font data sources contain glyphs for a character used in a string, the character in question will be replaced with a box displaying its hexadecimal code.
+
+ [codeblocks]
+ [gdscript]
+ var f = load("res://BarlowCondensed-Bold.ttf")
+ $"Label".set("custom_fonts/font", f)
+ $"Label".set("custom_fonts/font_size", 64)
+ [/gdscript]
+ [csharp]
+ var f = ResourceLoader.Load&lt;FontFile&gt;("res://BarlowCondensed-Bold.ttf");
+ GetNode("Label").Set("custom_fonts/font", f);
+ GetNode("Label").Set("custom_font_sizes/font_size", 64);
+ [/csharp]
+ [/codeblocks]
</description>
<tutorials>
</tutorials>
@@ -51,14 +70,7 @@
[b]Note:[/b] This function will not remove glyphs associated with the texture, use [method remove_glyph] to remove them manually.
</description>
</method>
- <method name="find_cache" qualifiers="const">
- <return type="RID" />
- <argument index="0" name="variation_coordinates" type="Dictionary" />
- <description>
- Returns existing or creates a new font cache entry for the specified variation coordinates.
- </description>
- </method>
- <method name="get_ascent" qualifiers="const">
+ <method name="get_cache_ascent" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
@@ -72,25 +84,46 @@
Returns number of the font cache entries.
</description>
</method>
- <method name="get_cache_rid" qualifiers="const">
- <return type="RID" />
+ <method name="get_cache_descent" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="get_cache_scale" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="get_cache_underline_position" qualifiers="const">
+ <return type="float" />
<argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
<description>
- Returns text server font cache entry resource id.
</description>
</method>
- <method name="get_descent" qualifiers="const">
+ <method name="get_cache_underline_thickness" qualifiers="const">
<return type="float" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<description>
- Returns font descent (number of pixels below the baseline).
</description>
</method>
- <method name="get_face_count" qualifiers="const">
+ <method name="get_embolden" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="cache_index" type="int" />
+ <description>
+ Returns embolden strength, if is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
+ <method name="get_face_index" qualifiers="const">
<return type="int" />
+ <argument index="0" name="cache_index" type="int" />
<description>
- Returns number of faces in the TrueType / OpenType collection.
+ Recturns an active face index in the TrueType / OpenType collection.
</description>
</method>
<method name="get_glyph_advance" qualifiers="const">
@@ -186,14 +219,6 @@
Returns list of language support overrides.
</description>
</method>
- <method name="get_scale" qualifiers="const">
- <return type="float" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <description>
- Returns scaling factor of the color bitmap font.
- </description>
- </method>
<method name="get_script_support_override" qualifiers="const">
<return type="bool" />
<argument index="0" name="script" type="String" />
@@ -214,34 +239,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
- <method name="get_spacing" qualifiers="const">
- <return type="int" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing_type" type="int" enum="TextServer.SpacingType" />
- <description>
- Returns extra spacing added between glyphs in pixels.
- </description>
- </method>
- <method name="get_supported_chars" qualifiers="const">
- <return type="String" />
- <description>
- Returns a string containing all the characters available in the font.
- </description>
- </method>
- <method name="get_supported_feature_list" qualifiers="const">
- <return type="Dictionary" />
- <description>
- Returns list of OpenType features supported by font.
- </description>
- </method>
- <method name="get_supported_variation_list" qualifiers="const">
- <return type="Dictionary" />
- <description>
- Returns list of supported [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url], each coordinate is returned as [code]tag: Vector3i(min_value,max_value,default_value)[/code].
- Font variations allow for continuous change of glyph characteristics along some given design axis, such as weight, width or slant.
- </description>
- </method>
<method name="get_texture_count" qualifiers="const">
<return type="int" />
<argument index="0" name="cache_index" type="int" />
@@ -268,48 +265,18 @@
Returns a copy of the array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
- <method name="get_underline_position" qualifiers="const">
- <return type="float" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <description>
- Returns pixel offset of the underline below the baseline.
- </description>
- </method>
- <method name="get_underline_thickness" qualifiers="const">
- <return type="float" />
+ <method name="get_transform" qualifiers="const">
+ <return type="Transform2D" />
<argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
<description>
- Returns thickness of the underline in pixels.
+ Returns 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
</description>
</method>
<method name="get_variation_coordinates" qualifiers="const">
<return type="Dictionary" />
<argument index="0" name="cache_index" type="int" />
<description>
- Returns variation coordinates for the specified font cache entry. See [method get_supported_variation_list] for more info.
- </description>
- </method>
- <method name="has_char" qualifiers="const">
- <return type="bool" />
- <argument index="0" name="char" type="int" />
- <description>
- Returns [code]true[/code] if a Unicode [code]char[/code] is available in the font.
- </description>
- </method>
- <method name="is_language_supported" qualifiers="const">
- <return type="bool" />
- <argument index="0" name="language" type="String" />
- <description>
- Returns [code]true[/code], if font supports given language ([url=https://en.wikipedia.org/wiki/ISO_639-1]ISO 639[/url] code).
- </description>
- </method>
- <method name="is_script_supported" qualifiers="const">
- <return type="bool" />
- <argument index="0" name="script" type="String" />
- <description>
- Returns [code]true[/code], if font supports given script ([url=https://en.wikipedia.org/wiki/ISO_15924]ISO 15924[/url] code).
+ Returns variation coordinates for the specified font cache entry. See [method Font.get_supported_variation_list] for more info.
</description>
</method>
<method name="load_bitmap_font">
@@ -324,8 +291,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<description>
- Loads a TrueType (.ttf), TrueType collection (.ttc), OpenType (.otf), OpenType collection (.otc), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
- [b]Note:[/b] Use [member face_index] to select specific face from the collection file.
+ Loads a TrueType (.ttf), OpenType (.otf), WOFF (.woff), WOFF2 (.woff2) or Type 1 (.pfb, .pfm) dynamic font from file [code]path[/code].
[b]Warning:[/b] This method should only be used in the editor or in cases when you need to load external fonts at run-time, such as fonts located at the [code]user://[/code] directory.
</description>
</method>
@@ -383,8 +349,8 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
- Removes specified texture from font cache entry.
- [b]Note:[/b] This function will not remove glyphs associated with the texture, remove them manually, using [method remove_glyph].
+ Removes specified texture from the cache entry.
+ [b]Note:[/b] This function will not remove glyphs associated with the texture. Remove them manually using [method remove_glyph].
</description>
</method>
<method name="render_glyph">
@@ -393,7 +359,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="index" type="int" />
<description>
- Renders specified glyph the the font cache texture.
+ Renders specified glyph to the font cache texture.
</description>
</method>
<method name="render_range">
@@ -406,22 +372,60 @@
Renders the range of characters to the font cache texture.
</description>
</method>
- <method name="set_ascent">
+ <method name="set_cache_ascent">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="ascent" type="float" />
<description>
- Sets the font ascent (number of pixels above the baseline).
</description>
</method>
- <method name="set_descent">
+ <method name="set_cache_descent">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="size" type="int" />
<argument index="2" name="descent" type="float" />
<description>
- Sets the font descent (number of pixels below the baseline).
+ </description>
+ </method>
+ <method name="set_cache_scale">
+ <return type="void" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="scale" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="set_cache_underline_position">
+ <return type="void" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="underline_position" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="set_cache_underline_thickness">
+ <return type="void" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="size" type="int" />
+ <argument index="2" name="underline_thickness" type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="set_embolden">
+ <return type="void" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="strength" type="float" />
+ <description>
+ Sets embolden strength, if is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
+ <method name="set_face_index">
+ <return type="void" />
+ <argument index="0" name="cache_index" type="int" />
+ <argument index="1" name="face_index" type="int" />
+ <description>
+ Sets an active face index in the TrueType / OpenType collection.
</description>
</method>
<method name="set_glyph_advance">
@@ -490,16 +494,7 @@
<argument index="0" name="language" type="String" />
<argument index="1" name="supported" type="bool" />
<description>
- Adds override for [method is_language_supported].
- </description>
- </method>
- <method name="set_scale">
- <return type="void" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="scale" type="float" />
- <description>
- Sets scaling factor of the color bitmap font.
+ Adds override for [method Font.is_language_supported].
</description>
</method>
<method name="set_script_support_override">
@@ -507,17 +502,7 @@
<argument index="0" name="script" type="String" />
<argument index="1" name="supported" type="bool" />
<description>
- Adds override for [method is_script_supported].
- </description>
- </method>
- <method name="set_spacing">
- <return type="void" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing_type" type="int" enum="TextServer.SpacingType" />
- <argument index="3" name="value" type="int" />
- <description>
- Sets extra spacing added between glyphs in pixels.
+ Adds override for [method Font.is_script_supported].
</description>
</method>
<method name="set_texture_image">
@@ -540,22 +525,12 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty (for the fonts without dynamic glyph generation support).
</description>
</method>
- <method name="set_underline_position">
+ <method name="set_transform">
<return type="void" />
<argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="underline_position" type="float" />
+ <argument index="1" name="transform" type="Transform2D" />
<description>
- Sets pixel offset of the underline below the baseline.
- </description>
- </method>
- <method name="set_underline_thickness">
- <return type="void" />
- <argument index="0" name="cache_index" type="int" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="underline_thickness" type="float" />
- <description>
- Sets thickness of the underline in pixels.
+ Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
</description>
</method>
<method name="set_variation_coordinates">
@@ -563,7 +538,7 @@
<argument index="0" name="cache_index" type="int" />
<argument index="1" name="variation_coordinates" type="Dictionary" />
<description>
- Sets variation coordinates for the specified font cache entry. See [method get_supported_variation_list] for more info.
+ Sets variation coordinates for the specified font cache entry. See [method Font.get_supported_variation_list] for more info.
</description>
</method>
</methods>
@@ -574,11 +549,8 @@
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file.
</member>
- <member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
- If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
- </member>
- <member name="face_index" type="int" setter="set_face_index" getter="get_face_index" default="0">
- Active face index in the TrueType / OpenType collection file.
+ <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
+ Array of fallback [Font]s.
</member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts.
@@ -619,9 +591,5 @@
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
</member>
- <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
- 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
- For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
- </member>
</members>
</class>
diff --git a/doc/classes/FontVariation.xml b/doc/classes/FontVariation.xml
new file mode 100644
index 0000000000..a1b96fb137
--- /dev/null
+++ b/doc/classes/FontVariation.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="FontVariation" inherits="Font" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Variation of the [Font].
+ </brief_description>
+ <description>
+ OpenType variations, simulated bold / slant, and additional font settings like OpenType features and extra spacing.
+
+ To use simulated bold font variant:
+ [codeblocks]
+ [gdscript]
+ var fv = FontVariation.new()
+ fv.set_base_font(load("res://BarlowCondensed-Regular.ttf"))
+ fv.set_variation_embolden(1.2);
+ $"Label".set("custom_fonts/font", fv)
+ $"Label".set("custom_fonts/font_size", 64)
+ [/gdscript]
+ [csharp]
+ var fv = new FontVariation();
+ fv.SetBaseFont(ResourceLoader.Load&lt;FontFile&gt;("res://BarlowCondensed-Regular.ttf"));
+ fv.SetVariationEmbolden(1.2);
+ GetNode("Label").Set("custom_fonts/font", fv);
+ GetNode("Label").Set("custom_font_sizes/font_size", 64);
+ [/csharp]
+ [/codeblocks]
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="set_spacing">
+ <return type="void" />
+ <argument index="0" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <argument index="1" name="value" type="int" />
+ <description>
+ Sets the spacing for [code]type[/code] (see [enum TextServer.SpacingType]) to [code]value[/code] in pixels (not relative to the font size).
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="base_font" type="Font" setter="set_base_font" getter="get_base_font">
+ Base font used to create a variation. If not set, default [Theme] font is used.
+ </member>
+ <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
+ Array of fallback [Font]s. If not set [member base_font] fallback are ussed.
+ </member>
+ <member name="opentype_features" type="Dictionary" setter="set_opentype_features" getter="get_opentype_features" default="{}">
+ A set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
+ </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>
+ <member name="spacing_glyph" type="int" setter="set_spacing" getter="get_spacing" default="0">
+ Extra spacing between graphical glyphs
+ </member>
+ <member name="spacing_space" type="int" setter="set_spacing" getter="get_spacing" default="0">
+ Extra width of the space glyphs.
+ </member>
+ <member name="spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
+ Extra spacing at the top of the line in pixels.
+ </member>
+ <member name="variation_embolden" type="float" setter="set_variation_embolden" getter="get_variation_embolden" default="0.0">
+ If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ [b]Note:[/b] Emboldened fonts might have self-intersecting outlines, which will prevent MSDF fonts and [TextMesh] from working correctly.
+ </member>
+ <member name="variation_face_index" type="int" setter="set_variation_face_index" getter="get_variation_face_index" default="0">
+ Active face index in the TrueType / OpenType collection file.
+ </member>
+ <member name="variation_opentype" type="Dictionary" setter="set_variation_opentype" getter="get_variation_opentype" default="{}">
+ Font OpenType variation coordinates. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]OpenType variation tags[/url].
+ </member>
+ <member name="variation_transform" type="Transform2D" setter="set_variation_transform" getter="get_variation_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index f261da8413..36dbae1d74 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -17,12 +17,6 @@
Disables all input and output slots of the GraphNode.
</description>
</method>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="clear_slot">
<return type="void" />
<argument index="0" name="idx" type="int" />
@@ -98,13 +92,6 @@
Returns the type of the output connection [code]idx[/code].
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
<method name="get_slot_color_left" qualifiers="const">
<return type="Color" />
<argument index="0" name="idx" type="int" />
@@ -154,14 +141,6 @@
Returns [code]true[/code] if right (output) side of the slot [code]idx[/code] is enabled.
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
<method name="set_slot">
<return type="void" />
<argument index="0" name="idx" type="int" />
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index 166923314f..f138b9087b 100644
--- a/doc/classes/HTTPRequest.xml
+++ b/doc/classes/HTTPRequest.xml
@@ -106,8 +106,7 @@
if error != OK:
push_error("Couldn't load the image.")
- var texture = ImageTexture.new()
- texture.create_from_image(image)
+ var texture = ImageTexture.create_from_image(image)
# Display the image in a TextureRect node.
var texture_rect = TextureRect.new()
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 43b03ce65e..31bd938c40 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -308,6 +308,13 @@
[b]Note:[/b] Godot's BMP module doesn't support 16-bit per pixel images. Only 1-bit, 4-bit, 8-bit, 24-bit, and 32-bit per pixel images are supported.
</description>
</method>
+ <method name="load_from_file" qualifiers="static">
+ <return type="Image" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ Creates a new [Image] and loads data from the specified file.
+ </description>
+ </method>
<method name="load_jpg_from_buffer">
<return type="int" enum="Error" />
<argument index="0" name="buffer" type="PackedByteArray" />
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index aecb4fc4b6..e668e2e7fd 100644
--- a/doc/classes/ImageTexture.xml
+++ b/doc/classes/ImageTexture.xml
@@ -6,10 +6,8 @@
<description>
A [Texture2D] based on an [Image]. For an image to be displayed, an [ImageTexture] has to be created from it using the [method create_from_image] method:
[codeblock]
- var texture = ImageTexture.new()
- var image = Image.new()
- image.load("res://icon.png")
- texture.create_from_image(image)
+ var image = Image.load_from_file("res://icon.png")
+ var texture = ImageTexture.create_from_image(image)
$Sprite2D.texture = texture
[/codeblock]
This way, textures can be created at run-time by loading images both from within the editor and externally.
@@ -31,11 +29,11 @@
<link title="Importing images">$DOCS_URL/tutorials/assets_pipeline/importing_images.html</link>
</tutorials>
<methods>
- <method name="create_from_image">
- <return type="void" />
+ <method name="create_from_image" qualifiers="static">
+ <return type="ImageTexture" />
<argument index="0" name="image" type="Image" />
<description>
- Initializes the texture by allocating and setting the data from an [Image].
+ Creates a new [ImageTexture] and initializes it by allocating and setting the data from an [Image].
</description>
</method>
<method name="get_format" qualifiers="const">
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 66683fa0ee..e73021ead4 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -375,6 +375,7 @@
<member name="use_accumulated_input" type="bool" setter="set_use_accumulated_input" getter="is_using_accumulated_input">
If [code]true[/code], similar input events sent by the operating system are accumulated. When input accumulation is enabled, all input events generated during a frame will be merged and emitted when the frame is done rendering. Therefore, this limits the number of input method calls per second to the rendering FPS.
Input accumulation can be disabled to get slightly more precise/reactive input at the cost of increased CPU usage. In applications where drawing freehand lines is required, input accumulation should generally be disabled while the user is drawing the line to get results that closely follow the actual input.
+ [b]Note:[/b] Input accumulation is [i]enabled[/i] by default.
</member>
</members>
<signals>
diff --git a/doc/classes/InputEventMouseMotion.xml b/doc/classes/InputEventMouseMotion.xml
index ad74204d82..83aad587a5 100644
--- a/doc/classes/InputEventMouseMotion.xml
+++ b/doc/classes/InputEventMouseMotion.xml
@@ -12,6 +12,10 @@
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
</tutorials>
<members>
+ <member name="pen_inverted" type="bool" setter="set_pen_inverted" getter="get_pen_inverted" default="false">
+ Returns [code]true[/code] when using the eraser end of a stylus pen.
+ [b]Note:[/b] This property is implemented on Linux, macOS and Windows.
+ </member>
<member name="pressure" type="float" setter="set_pressure" getter="get_pressure" default="0.0">
Represents the pressure the user puts on the pen. Ranges from [code]0.0[/code] to [code]1.0[/code].
</member>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index d52234e9ac..15c97b0838 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -38,13 +38,6 @@
Removes all items from the list.
</description>
</method>
- <method name="clear_item_opentype_features">
- <return type="void" />
- <argument index="0" name="idx" type="int" />
- <description>
- Removes all OpenType features from the item's text.
- </description>
- </method>
<method name="deselect">
<return type="void" />
<argument index="0" name="idx" type="int" />
@@ -122,14 +115,6 @@
Returns the metadata value of the specified index.
</description>
</method>
- <method name="get_item_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="idx" type="int" />
- <argument index="1" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code] of the item's text.
- </description>
- </method>
<method name="get_item_text" qualifiers="const">
<return type="String" />
<argument index="0" name="idx" type="int" />
@@ -302,15 +287,6 @@
Sets a value (of any type) to be stored with the item associated with the specified index.
</description>
</method>
- <method name="set_item_opentype_feature">
- <return type="void" />
- <argument index="0" name="idx" type="int" />
- <argument index="1" name="tag" type="String" />
- <argument index="2" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code] for the item's text. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
<method name="set_item_selectable">
<return type="void" />
<argument index="0" name="idx" type="int" />
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index b5f045621b..1eac58b9f2 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -11,12 +11,6 @@
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
</tutorials>
<methods>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="get_line_count" qualifiers="const">
<return type="int" />
<description>
@@ -32,13 +26,6 @@
If there're no lines returns font size in pixels.
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
<method name="get_total_character_count" qualifiers="const">
<return type="int" />
<description>
@@ -51,14 +38,6 @@
Returns the number of lines shown. Useful if the [Label]'s height cannot currently display all lines.
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
</methods>
<members>
<member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="TextServer.AutowrapMode" default="0">
@@ -119,7 +98,7 @@
Default text [Color] of the [Label].
</theme_item>
<theme_item name="font_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
- The tint of [Font]'s outline.
+ The tint of text outline.
</theme_item>
<theme_item name="font_shadow_color" data_type="color" type="Color" default="Color(0, 0, 0, 0)">
[Color] of the text's shadow effect.
diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml
index 47126575f7..2c3c27079a 100644
--- a/doc/classes/Label3D.xml
+++ b/doc/classes/Label3D.xml
@@ -9,12 +9,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="generate_triangle_mesh" qualifiers="const">
<return type="TriangleMesh" />
<description>
@@ -28,13 +22,6 @@
Returns the value of the specified flag.
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
<method name="set_draw_flag">
<return type="void" />
<argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
@@ -43,14 +30,6 @@
If [code]true[/code], the specified flag will be enabled. See [enum Label3D.DrawFlags] for a list of flags.
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
</methods>
<members>
<member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0">
@@ -72,7 +51,7 @@
If [code]true[/code], the label is rendered at the same size regardless of distance.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
- [Font] used for the [Label3D]'s text.
+ Font configuration used to display text.
</member>
<member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
Font size of the [Label3D]'s text.
@@ -96,7 +75,7 @@
The text drawing offset (in pixels).
</member>
<member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color(0, 0, 0, 1)">
- The tint of [Font]'s outline.
+ The tint of text outline.
</member>
<member name="outline_render_priority" type="int" setter="set_outline_render_priority" getter="get_outline_render_priority" default="-1">
Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects.
diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml
index 4d8fd63257..0ebd83c882 100644
--- a/doc/classes/Light3D.xml
+++ b/doc/classes/Light3D.xml
@@ -73,6 +73,7 @@
</member>
<member name="light_projector" type="Texture2D" setter="set_projector" getter="get_projector">
[Texture2D] projected by light. [member shadow_enabled] must be on for the projector to work. Light projectors make the light appear as if it is shining through a colored but transparent object, almost like light shining through stained-glass.
+ [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for light projector textures is set globally with [member ProjectSettings.rendering/textures/light_projectors/filter].
</member>
<member name="light_size" type="float" setter="set_param" getter="get_param" default="0.0">
The size of the light in Godot units. Only available for [OmniLight3D]s and [SpotLight3D]s. Increasing this value will make the light fade out slower and shadows appear blurrier. This can be used to simulate area lights to an extent.
diff --git a/doc/classes/LightmapGI.xml b/doc/classes/LightmapGI.xml
index ffde0d95ce..c0766cd1ec 100644
--- a/doc/classes/LightmapGI.xml
+++ b/doc/classes/LightmapGI.xml
@@ -21,7 +21,7 @@
Number of light bounces that are taken into account during baking. Higher values result in brighter, more realistic lighting, at the cost of longer bake times. If set to [code]0[/code], only environment lighting, direct light and emissive lighting is baked.
</member>
<member name="directional" type="bool" setter="set_directional" getter="is_directional" default="false">
- If [code]true[/code], bakes lightmaps to contain directional information as spherical harmonics. This results in more realistic lighting appearance, especially with normal mapped materials and for lights that their have direct light baked ([member Light3D.light_bake_mode] set to [constant Light3D.BAKE_STATIC]). The directional information is also used to provide rough reflections for static and dynamic objects. This has a small run-time performance cost as the shader has to perform more work to interpret the direction information from the lightmap. Directional lightmaps also take longer to bake and result in larger file sizes.
+ If [code]true[/code], bakes lightmaps to contain directional information as spherical harmonics. This results in more realistic lighting appearance, especially with normal mapped materials and for lights that have their direct light baked ([member Light3D.light_bake_mode] set to [constant Light3D.BAKE_STATIC]). The directional information is also used to provide rough reflections for static and dynamic objects. This has a small run-time performance cost as the shader has to perform more work to interpret the direction information from the lightmap. Directional lightmaps also take longer to bake and result in larger file sizes.
[b]Note:[/b] The property's name has no relationship with [DirectionalLight3D]. [member directional] works with all light types.
</member>
<member name="environment_custom_color" type="Color" setter="set_environment_custom_color" getter="get_environment_custom_color">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 55e012ee0c..84471bafc0 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -37,12 +37,6 @@
Erases the [LineEdit]'s [member text].
</description>
</method>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="delete_char_at_caret">
<return type="void" />
<description>
@@ -70,13 +64,6 @@
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member Window.visible] property.
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
<method name="get_scroll_offset" qualifiers="const">
<return type="int" />
<description>
@@ -149,14 +136,6 @@
Selects the whole [String].
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
</methods>
<members>
<member name="alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="0">
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index ba80504caf..7c6ff2d4e1 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -9,29 +9,6 @@
</description>
<tutorials>
</tutorials>
- <methods>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
- </methods>
<members>
<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.
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index ac434af4fa..ff2afd595a 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -281,6 +281,13 @@
<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_position" type="Vector3" setter="set_global_position" getter="get_global_position">
+ Global position of this node. This is equivalent to [code]global_transform.origin[/code].
+ </member>
+ <member name="global_rotation" type="Vector3" setter="set_global_rotation" getter="get_global_rotation">
+ Rotation part of the global transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
+ [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="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 00c5dcaa3d..d9e0680a38 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -87,6 +87,12 @@
[/codeblocks]
</description>
</method>
+ <method name="get_concatenated_names" qualifiers="const">
+ <return type="StringName" />
+ <description>
+ Returns all paths concatenated with a slash character ([code]/[/code]) as separator without subnames.
+ </description>
+ </method>
<method name="get_concatenated_subnames" qualifiers="const">
<return type="StringName" />
<description>
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 5d0861bcf3..3af3bb8697 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -409,7 +409,7 @@
<return type="PackedFloat32Array" />
<description>
Returns a copy of the data converted to a [PackedFloat32Array], where each block of 4 bytes has been converted to a 32-bit float (C++ [code]float[/code]).
- The size of the new array will be [code]byte_array.size() / 4[/code].
+ The size of the input array must be a multiple of 4 (size of 32-bit float). The size of the new array will be [code]byte_array.size() / 4[/code].
If the original data can't be converted to 32-bit floats, the resulting data is undefined.
</description>
</method>
@@ -417,7 +417,7 @@
<return type="PackedFloat64Array" />
<description>
Returns a copy of the data converted to a [PackedFloat64Array], where each block of 8 bytes has been converted to a 64-bit float (C++ [code]double[/code], Godot [float]).
- The size of the new array will be [code]byte_array.size() / 8[/code].
+ The size of the input array must be a multiple of 8 (size of 64-bit double). The size of the new array will be [code]byte_array.size() / 8[/code].
If the original data can't be converted to 64-bit floats, the resulting data is undefined.
</description>
</method>
@@ -425,15 +425,15 @@
<return type="PackedInt32Array" />
<description>
Returns a copy of the data converted to a [PackedInt32Array], where each block of 4 bytes has been converted to a signed 32-bit integer (C++ [code]int32_t[/code]).
- The size of the new array will be [code]byte_array.size() / 4[/code].
+ The size of the input array must be a multiple of 4 (size of 32-bit integer). The size of the new array will be [code]byte_array.size() / 4[/code].
If the original data can't be converted to signed 32-bit integers, the resulting data is undefined.
</description>
</method>
<method name="to_int64_array" qualifiers="const">
<return type="PackedInt64Array" />
<description>
- Returns a copy of the data converted to a [PackedInt64Array], where each block of 4 bytes has been converted to a signed 64-bit integer (C++ [code]int64_t[/code], Godot [int]).
- The size of the new array will be [code]byte_array.size() / 8[/code].
+ Returns a copy of the data converted to a [PackedInt64Array], where each block of 8 bytes has been converted to a signed 64-bit integer (C++ [code]int64_t[/code], Godot [int]).
+ The size of the input array must be a multiple of 8 (size of 64-bit integer). The size of the new array will be [code]byte_array.size() / 8[/code].
If the original data can't be converted to signed 64-bit integers, the resulting data is undefined.
</description>
</method>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 885bedbc04..354fbd462c 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -77,28 +77,30 @@
Each particle's rotation will be animated along this [CurveTexture].
</member>
<member name="angle_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum angle.
+ Maximum initial rotation applied to each particle, in degrees.
+ Only applied when [member particle_flag_disable_z] or [member particle_flag_rotate_y] are [code]true[/code] or the [BaseMaterial3D] being used to draw the particle is using [constant BaseMaterial3D.BILLBOARD_PARTICLES].
</member>
<member name="angle_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum angle.
+ Minimum equivalent of [member angle_max].
</member>
<member name="angular_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's angular velocity (rotation speed) will vary along this [CurveTexture] over its lifetime.
</member>
<member name="angular_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
Maximum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second.
+ Only applied when [member particle_flag_disable_z] or [member particle_flag_rotate_y] are [code]true[/code] or the [BaseMaterial3D] being used to draw the particle is using [constant BaseMaterial3D.BILLBOARD_PARTICLES].
</member>
<member name="angular_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second.
+ Minimum equivalent of [member angular_velocity_max].
</member>
<member name="anim_offset_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's animation offset will vary along this [CurveTexture].
</member>
<member name="anim_offset_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum animation offset.
+ Maximum animation offset that corresponds to frame index in the texture. [code]0[/code] is the first frame, [code]1[/code] is the last one. See [member CanvasItemMaterial.particles_animation].
</member>
<member name="anim_offset_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum animation offset.
+ Minimum equivalent of [member anim_offset_max].
</member>
<member name="anim_speed_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's animation speed will vary along this [CurveTexture].
@@ -108,7 +110,7 @@
With animation speed greater than [code]1[/code], remember to enable [member CanvasItemMaterial.particles_anim_loop] property if you want the animation to repeat.
</member>
<member name="anim_speed_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum particle animation speed.
+ Minimum equivalent of [member anim_speed_max].
</member>
<member name="attractor_interaction_enabled" type="bool" setter="set_attractor_interaction_enabled" getter="is_attractor_interaction_enabled" default="true">
True if the interaction with particle attractors is enabled.
@@ -138,8 +140,10 @@
Damping will vary along this [CurveTexture].
</member>
<member name="damping_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
+ The maximum rate at which particles lose velocity. For example value of [code]100[/code] means that the particle will go from [code]100[/code] velocity to [code]0[/code] in [code]1[/code] second.
</member>
<member name="damping_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
+ Minimum equivalent of [member damping_max].
</member>
<member name="direction" type="Vector3" setter="set_direction" getter="get_direction" default="Vector3(1, 0, 0)">
Unit vector specifying the particles' emission direction.
@@ -187,16 +191,16 @@
Each particle's hue will vary along this [CurveTexture].
</member>
<member name="hue_variation_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum hue variation.
+ Maximum initial hue variation applied to each particle. It will shift the particle color's hue.
</member>
<member name="hue_variation_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum hue variation.
+ Minimum equivalent of [member hue_variation_max].
</member>
<member name="initial_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum initial velocity.
+ Maximum initial velocity magnitude for each particle. Direction comes from [member direction] and [member spread].
</member>
<member name="initial_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum initial velocity.
+ Minimum equivalent of [member initial_velocity_max].
</member>
<member name="lifetime_randomness" type="float" setter="set_lifetime_randomness" getter="get_lifetime_randomness" default="0.0">
Particle lifetime randomness ratio. The lifetime will be multiplied by a value interpolated between [code]1.0[/code] and a random number less than one. For example a random ratio of [code]0.4[/code] would scale the original lifetime between [code]0.4-1.0[/code] of its original value.
@@ -205,19 +209,20 @@
Each particle's linear acceleration will vary along this [CurveTexture].
</member>
<member name="linear_accel_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum linear acceleration.
+ Maximum linear acceleration applied to each particle in the direction of motion.
</member>
<member name="linear_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum linear acceleration.
+ Minimum equivalent of [member linear_accel_min].
</member>
<member name="orbit_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's orbital velocity will vary along this [CurveTexture].
</member>
<member name="orbit_velocity_max" type="float" setter="set_param_max" getter="get_param_max">
- Maximum orbit velocity.
+ Maximum orbital velocity applied to each particle. Makes the particles circle around origin. Specified in number of full rotations around origin per second.
+ Only available when [member particle_flag_disable_z] is [code]true[/code].
</member>
<member name="orbit_velocity_min" type="float" setter="set_param_min" getter="get_param_min">
- Minimum orbit velocity.
+ Minimum equivalent of [member orbit_velocity_max].
</member>
<member name="particle_flag_align_y" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
Align Y axis of particle with the direction of its velocity.
@@ -232,19 +237,19 @@
Each particle's radial acceleration will vary along this [CurveTexture].
</member>
<member name="radial_accel_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum radial acceleration.
+ Maximum radial acceleration applied to each particle. Makes particle accelerate away from the origin or towards it if negative.
</member>
<member name="radial_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum radial acceleration.
+ Minimum equivalent of [member radial_accel_max].
</member>
<member name="scale_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
Each particle's scale will vary along this [CurveTexture]. If a [CurveXYZTexture] is supplied instead, the scale will be separated per-axis.
</member>
<member name="scale_max" type="float" setter="set_param_max" getter="get_param_max" default="1.0">
- Maximum scale.
+ Maximum initial scale applied to each particle.
</member>
<member name="scale_min" type="float" setter="set_param_min" getter="get_param_min" default="1.0">
- Minimum scale.
+ Minimum equivalent of [member scale_max].
</member>
<member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0">
Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees.
@@ -261,10 +266,10 @@
Each particle's tangential acceleration will vary along this [CurveTexture].
</member>
<member name="tangential_accel_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0">
- Maximum tangential acceleration.
+ Maximum tangential acceleration applied to each particle. Tangential acceleration is perpendicular to the particle's velocity giving the particles a swirling motion.
</member>
<member name="tangential_accel_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0">
- Minimum tangential acceleration.
+ Minimum equivalent of [member tangential_accel_max].
</member>
</members>
<constants>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 73413b379e..5da2196f29 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -182,13 +182,6 @@
Removes all items from the [PopupMenu].
</description>
</method>
- <method name="clear_item_opentype_features">
- <return type="void" />
- <argument index="0" name="index" type="int" />
- <description>
- Removes all OpenType features form the item's text.
- </description>
- </method>
<method name="get_current_index" qualifiers="const">
<return type="int" />
<description>
@@ -244,14 +237,6 @@
Returns the metadata of the specified item, which might be of any type. You can set it with [method set_item_metadata], which provides a simple way of assigning context data to items.
</description>
</method>
- <method name="get_item_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="index" type="int" />
- <argument index="1" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code] of the item's text.
- </description>
- </method>
<method name="get_item_shortcut" qualifiers="const">
<return type="Shortcut" />
<argument index="0" name="index" type="int" />
@@ -452,15 +437,6 @@
Sets the state of a multistate item. See [method add_multistate_item] for details.
</description>
</method>
- <method name="set_item_opentype_feature">
- <return type="void" />
- <argument index="0" name="index" type="int" />
- <argument index="1" name="tag" type="String" />
- <argument index="2" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code] for the item's text. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
<method name="set_item_shortcut">
<return type="void" />
<argument index="0" name="index" type="int" />
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 553005c4c4..2a47d4af25 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -203,6 +203,9 @@
Path to an image used as the boot splash. If left empty, the default Godot Engine splash will be displayed instead.
[b]Note:[/b] Only effective if [member application/boot_splash/show_image] is [code]true[/code].
</member>
+ <member name="application/boot_splash/minimum_display_time" type="int" setter="" getter="" default="0">
+ Minimum boot splash display time (in milliseconds). It is not recommended to set too high values for this setting.
+ </member>
<member name="application/boot_splash/show_image" type="bool" setter="" getter="" default="true">
If [code]true[/code], displays the image specified in [member application/boot_splash/image] when the engine starts. If [code]false[/code], only displays the plain color specified in [member application/boot_splash/bg_color].
</member>
@@ -628,7 +631,7 @@
Path to a custom [Font] resource to use as default for all GUI elements of the project.
</member>
<member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true">
- If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontData.antialiased].
+ If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontFile.antialiased].
</member>
<member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false">
If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps).
@@ -636,7 +639,7 @@
[b]Note:[/b] This setting does not affect custom [Font]s used within the project.
</member>
<member name="gui/theme/default_font_hinting" type="int" setter="" getter="" default="1">
- Default font hinting mode. See [member FontData.hinting].
+ Default font hinting mode. See [member FontFile.hinting].
</member>
<member name="gui/theme/default_font_multichannel_signed_distance_field" type="bool" setter="" getter="" default="false">
If set to [code]true[/code], the default font will use multichannel signed distance field (MSDF) for crisp rendering at any size. Since this approach does not rely on rasterizing the font every time its size changes, this allows for resizing the font in real-time without any performance penalty. Text will also not look grainy for [Control]s that are scaled down (or for [Label3D]s viewed from a long distance).
@@ -644,7 +647,7 @@
[b]Note:[/b] This setting does not affect custom [Font]s used within the project.
</member>
<member name="gui/theme/default_font_subpixel_positioning" type="int" setter="" getter="" default="1">
- Default font glyph sub-pixel positioning mode. See [member FontData.subpixel_positioning].
+ Default font glyph sub-pixel positioning mode. See [member FontFile.subpixel_positioning].
</member>
<member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0">
</member>
diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml
index 815c7e8813..213d8c585a 100644
--- a/doc/classes/ResourceSaver.xml
+++ b/doc/classes/ResourceSaver.xml
@@ -37,7 +37,7 @@
<return type="int" enum="Error" />
<argument index="0" name="path" type="String" />
<argument index="1" name="resource" type="Resource" />
- <argument index="2" name="flags" type="int" default="0" />
+ <argument index="2" name="flags" type="int" enum="ResourceSaver.SaverFlags" default="0" />
<description>
Saves a resource to disk to the given path, using a [ResourceFormatSaver] that recognizes the resource object.
The [code]flags[/code] bitmask can be specified to customize the save behavior using [enum SaverFlags] flags.
@@ -46,28 +46,28 @@
</method>
</methods>
<constants>
- <constant name="FLAG_NONE" value="0" enum="SaverFlags">
+ <constant name="FLAG_NONE" value="0" enum="SaverFlags" is_bitfield="true">
No resource saving option.
</constant>
- <constant name="FLAG_RELATIVE_PATHS" value="1" enum="SaverFlags">
+ <constant name="FLAG_RELATIVE_PATHS" value="1" enum="SaverFlags" is_bitfield="true">
Save the resource with a path relative to the scene which uses it.
</constant>
- <constant name="FLAG_BUNDLE_RESOURCES" value="2" enum="SaverFlags">
+ <constant name="FLAG_BUNDLE_RESOURCES" value="2" enum="SaverFlags" is_bitfield="true">
Bundles external resources.
</constant>
- <constant name="FLAG_CHANGE_PATH" value="4" enum="SaverFlags">
+ <constant name="FLAG_CHANGE_PATH" value="4" enum="SaverFlags" is_bitfield="true">
Changes the [member Resource.resource_path] of the saved resource to match its new location.
</constant>
- <constant name="FLAG_OMIT_EDITOR_PROPERTIES" value="8" enum="SaverFlags">
+ <constant name="FLAG_OMIT_EDITOR_PROPERTIES" value="8" enum="SaverFlags" is_bitfield="true">
Do not save editor-specific metadata (identified by their [code]__editor[/code] prefix).
</constant>
- <constant name="FLAG_SAVE_BIG_ENDIAN" value="16" enum="SaverFlags">
+ <constant name="FLAG_SAVE_BIG_ENDIAN" value="16" enum="SaverFlags" is_bitfield="true">
Save as big endian (see [member File.big_endian]).
</constant>
- <constant name="FLAG_COMPRESS" value="32" enum="SaverFlags">
+ <constant name="FLAG_COMPRESS" value="32" enum="SaverFlags" is_bitfield="true">
Compress the resource on save using [constant File.COMPRESSION_ZSTD]. Only available for binary resource types.
</constant>
- <constant name="FLAG_REPLACE_SUBRESOURCE_PATHS" value="64" enum="SaverFlags">
+ <constant name="FLAG_REPLACE_SUBRESOURCE_PATHS" value="64" enum="SaverFlags" is_bitfield="true">
Take over the paths of the saved subresources (see [method Resource.take_over_path]).
</constant>
</constants>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 1294e5b58a..3c9e9b1bfc 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -276,18 +276,10 @@
Adds a [code][font][/code] tag to the tag stack. Overrides default fonts for its duration.
</description>
</method>
- <method name="push_font_features">
- <return type="void" />
- <argument index="0" name="opentype_features" type="Dictionary" />
- <description>
- Adds a [code][ot_feature][/code] tag to the tag stack. Overrides default OpenType font feature for its duration.
- </description>
- </method>
<method name="push_font_size">
<return type="void" />
<argument index="0" name="font_size" type="int" />
<description>
- Adds a [code][font_size][/code] tag to the tag stack. Overrides default font size for its duration.
</description>
</method>
<method name="push_hint">
diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml
index 0f757cf806..45d4cf44fa 100644
--- a/doc/classes/ScriptLanguageExtension.xml
+++ b/doc/classes/ScriptLanguageExtension.xml
@@ -174,6 +174,11 @@
<description>
</description>
</method>
+ <method name="_get_public_annotations" qualifiers="virtual const">
+ <return type="Dictionary[]" />
+ <description>
+ </description>
+ </method>
<method name="_get_public_constants" qualifiers="virtual const">
<return type="Dictionary" />
<description>
@@ -378,7 +383,9 @@
</constant>
<constant name="LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE" value="7" enum="LookupResultType">
</constant>
- <constant name="LOOKUP_RESULT_MAX" value="8" enum="LookupResultType">
+ <constant name="LOOKUP_RESULT_CLASS_ANNOTATION" value="8" enum="LookupResultType">
+ </constant>
+ <constant name="LOOKUP_RESULT_MAX" value="9" enum="LookupResultType">
</constant>
<constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation">
The option is local to the location of the code completion query - e.g. a local variable.
diff --git a/doc/classes/SkeletonProfile.xml b/doc/classes/SkeletonProfile.xml
new file mode 100644
index 0000000000..55a2ea6759
--- /dev/null
+++ b/doc/classes/SkeletonProfile.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonProfile" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Profile of a virtual skeleton used as a target for retargeting.
+ </brief_description>
+ <description>
+ This resource is used in [EditorScenePostImport]. Some parameters are referring to bones in [Skeleton3D], [Skin], [Animation], and some other nodes are rewritten based on the parameters of [SkeletonProfile].
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="get_bone_name" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the name of the bone at [code]bone_idx[/code] that will be the key name in the [BoneMap].
+ In the retargeting process, the returned bone name is the bone name of the target skeleton.
+ </description>
+ </method>
+ <method name="get_group" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the group of the bone at [code]bone_idx[/code].
+ </description>
+ </method>
+ <method name="get_group_name" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="group_idx" type="int" />
+ <description>
+ Returns the name of the group at [code]group_idx[/code] that will be the drawing group in the [BoneMap] editor.
+ </description>
+ </method>
+ <method name="get_handle_offset" qualifiers="const">
+ <return type="Vector2" />
+ <argument index="0" name="bone_idx" type="int" />
+ <description>
+ Returns the offset of the bone at [code]bone_idx[/code] that will be the button position in the [BoneMap] editor.
+ This is the offset with origin at the top left corner of the square.
+ </description>
+ </method>
+ <method name="get_texture" qualifiers="const">
+ <return type="Texture2D" />
+ <argument index="0" name="group_idx" type="int" />
+ <description>
+ Returns the texture of the group at [code]group_idx[/code] that will be the drawing group background image in the [BoneMap] editor.
+ </description>
+ </method>
+ <method name="set_bone_name">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="bone_name" type="StringName" />
+ <description>
+ Sets the name of the bone at [code]bone_idx[/code] that will be the key name in the [BoneMap].
+ In the retargeting process, the setting bone name is the bone name of the target skeleton.
+ </description>
+ </method>
+ <method name="set_group">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="group" type="StringName" />
+ <description>
+ Sets the group of the bone at [code]bone_idx[/code].
+ </description>
+ </method>
+ <method name="set_group_name">
+ <return type="void" />
+ <argument index="0" name="group_idx" type="int" />
+ <argument index="1" name="group_name" type="StringName" />
+ <description>
+ Sets the name of the group at [code]group_idx[/code] that will be the drawing group in the [BoneMap] editor.
+ </description>
+ </method>
+ <method name="set_handle_offset">
+ <return type="void" />
+ <argument index="0" name="bone_idx" type="int" />
+ <argument index="1" name="handle_offset" type="Vector2" />
+ <description>
+ Sets the offset of the bone at [code]bone_idx[/code] that will be the button position in the [BoneMap] editor.
+ This is the offset with origin at the top left corner of the square.
+ </description>
+ </method>
+ <method name="set_texture">
+ <return type="void" />
+ <argument index="0" name="group_idx" type="int" />
+ <argument index="1" name="texture" type="Texture2D" />
+ <description>
+ Sets the texture of the group at [code]group_idx[/code] that will be the drawing group background image in the [BoneMap] editor.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="bone_size" type="int" setter="set_bone_size" getter="get_bone_size" default="0">
+ </member>
+ <member name="group_size" type="int" setter="set_group_size" getter="get_group_size" default="0">
+ </member>
+ </members>
+ <signals>
+ <signal name="profile_updated">
+ <description>
+ This signal is emitted when change the value in profile. This is used to update key name in the [BoneMap] and to redraw the [BoneMap] editor.
+ [b]Note[/b]: This signal is not connected directly to editor to simplify the reference, instead it is passed on to editor through the [BoneMap].
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/SkeletonProfileHumanoid.xml b/doc/classes/SkeletonProfileHumanoid.xml
new file mode 100644
index 0000000000..065184244e
--- /dev/null
+++ b/doc/classes/SkeletonProfileHumanoid.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="SkeletonProfileHumanoid" inherits="SkeletonProfile" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ A [SkeletonProfile] as a preset that is optimized for the human form. This exists for standardization, so all parameters are read-only.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="bone_size" type="int" setter="set_bone_size" getter="get_bone_size" overrides="SkeletonProfile" default="56" />
+ <member name="group_size" type="int" setter="set_group_size" getter="get_group_size" overrides="SkeletonProfile" default="4" />
+ </members>
+</class>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index f4d453700c..9f197dae02 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -180,7 +180,22 @@
<argument index="0" name="values" type="Variant" />
<argument index="1" name="placeholder" type="String" default="&quot;{_}&quot;" />
<description>
- Formats the string by replacing all occurrences of [code]placeholder[/code] with [code]values[/code].
+ Formats the string by replacing all occurrences of [code]placeholder[/code] with the elements of [code]values[/code].
+ [code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in [code]placeholder[/code] will be replaced with the corresponding keys in advance. Array elements use their index as keys.
+ [codeblock]
+ # Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is named after it.
+ var use_array_values = "Waiting for {0} is a play by {1}, and {0} Engine is named after it."
+ print(use_array_values.format(["Godot", "Samuel Beckett"]))
+
+ # Prints: User 42 is Godot.
+ print("User {id} is {name}.".format({"id": 42, "name": "Godot"}))
+ [/codeblock]
+ Some additional handling is performed when [code]values[/code] is an array. If [code]placeholder[/code] does not contain an underscore, the elements of the array will be used to replace one occurrence of the placeholder in turn; If an array element is another 2-element array, it'll be interpreted as a key-value pair.
+ [codeblock]
+ # Prints: User 42 is Godot.
+ print("User {} is {}.".format([42, "Godot"], "{}"))
+ print("User {id} is {name}.".format([["id", 42], ["name", "Godot"]]))
+ [/codeblock]
</description>
</method>
<method name="get_base_dir" qualifiers="const">
diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml
index 74d02a84fd..d863e3c652 100644
--- a/doc/classes/StyleBox.xml
+++ b/doc/classes/StyleBox.xml
@@ -46,8 +46,8 @@
<argument index="0" name="canvas_item" type="RID" />
<argument index="1" name="rect" type="Rect2" />
<description>
- Draws this stylebox using a [CanvasItem] with given [RID].
- You can get a [RID] value using [method Object.get_instance_id] on a [CanvasItem]-derived node.
+ Draws this stylebox using a canvas item identified by the given [RID].
+ The [RID] value can either be the result of [method CanvasItem.get_canvas_item] called on an existing [CanvasItem]-derived node, or directly from creating a canvas item in the [RenderingServer] with [method RenderingServer.canvas_item_create].
</description>
</method>
<method name="get_center_size" qualifiers="const">
diff --git a/doc/classes/TabBar.xml b/doc/classes/TabBar.xml
index a8ed0d4286..79d52b70fb 100644
--- a/doc/classes/TabBar.xml
+++ b/doc/classes/TabBar.xml
@@ -17,13 +17,6 @@
Adds a new tab.
</description>
</method>
- <method name="clear_tab_opentype_features">
- <return type="void" />
- <argument index="0" name="tab_idx" type="int" />
- <description>
- Removes all OpenType features from the tab title.
- </description>
- </method>
<method name="ensure_tab_visible">
<return type="void" />
<argument index="0" name="idx" type="int" />
@@ -77,14 +70,6 @@
Returns the number of hidden tabs offsetted to the left.
</description>
</method>
- <method name="get_tab_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tab_idx" type="int" />
- <argument index="1" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code] of the tab title.
- </description>
- </method>
<method name="get_tab_rect" qualifiers="const">
<return type="Rect2" />
<argument index="0" name="tab_idx" type="int" />
@@ -175,15 +160,6 @@
Sets language code of tab title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</description>
</method>
- <method name="set_tab_opentype_feature">
- <return type="void" />
- <argument index="0" name="tab_idx" type="int" />
- <argument index="1" name="tag" type="String" />
- <argument index="2" name="values" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code] for the tab title. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
<method name="set_tab_text_direction">
<return type="void" />
<argument index="0" name="tab_idx" type="int" />
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 2de185903d..18a4893f03 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -85,12 +85,6 @@
Performs a full reset of [TextEdit], including undo history.
</description>
</method>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="clear_undo_history">
<return type="void" />
<description>
@@ -355,13 +349,6 @@
Returns the count to the next visible line from [code]line[/code] to [code]line + visible_amount[/code]. Can also count backwards. For example if a [TextEdit] has 5 lines with lines 2 and 3 hidden, calling this with [code]line = 1, visible_amount = 1[/code] would return 3.
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
<method name="get_pos_at_line_column" qualifiers="const">
<return type="Vector2i" />
<argument index="0" name="line" type="int" />
@@ -859,14 +846,6 @@
Sets the text for [code]gutter[/code] on [code]line[/code].
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
<method name="set_overtype_mode_enabled">
<return type="void" />
<argument index="0" name="enabled" type="bool" />
@@ -998,13 +977,16 @@
<member name="placeholder_text" type="String" setter="set_placeholder" getter="get_placeholder" default="&quot;&quot;">
Text shown when the [TextEdit] is empty. It is [b]not[/b] the [TextEdit]'s default value (see [member text]).
</member>
+ <member name="scroll_fit_content_height" type="bool" setter="set_fit_content_height_enabled" getter="is_fit_content_height_enabled" default="false">
+ If [code]true[/code], [TextEdit] will disable vertical scroll and fit minimum height to the number of visible lines.
+ </member>
<member name="scroll_horizontal" type="int" setter="set_h_scroll" getter="get_h_scroll" default="0">
If there is a horizontal scrollbar, this determines the current horizontal scroll value in pixels.
</member>
<member name="scroll_past_end_of_file" type="bool" setter="set_scroll_past_end_of_file_enabled" getter="is_scroll_past_end_of_file_enabled" default="false">
Allow scrolling past the last line into "virtual" space.
</member>
- <member name="scroll_smooth" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled" default="false">
+ <member name="scroll_smooth" type="bool" setter="set_smooth_scroll_enabled" getter="is_smooth_scroll_enabled" default="false">
Scroll smoothly over the text rather then jumping to the next location.
</member>
<member name="scroll_v_scroll_speed" type="float" setter="set_v_scroll_speed" getter="get_v_scroll_speed" default="80.0">
diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml
index f154cbbe9a..c3574980b1 100644
--- a/doc/classes/TextLine.xml
+++ b/doc/classes/TextLine.xml
@@ -22,11 +22,10 @@
<method name="add_string">
<return type="bool" />
<argument index="0" name="text" type="String" />
- <argument index="1" name="fonts" type="Font" />
- <argument index="2" name="size" type="int" />
- <argument index="3" name="opentype_features" type="Dictionary" default="{}" />
- <argument index="4" name="language" type="String" default="&quot;&quot;" />
- <argument index="5" name="meta" type="Variant" default="null" />
+ <argument index="1" name="font" type="Font" />
+ <argument index="2" name="font_size" type="int" />
+ <argument index="3" name="language" type="String" default="&quot;&quot;" />
+ <argument index="4" name="meta" type="Variant" default="null" />
<description>
Adds text span and font to draw it.
</description>
diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml
index 5a1501d2ca..17a0ca32e4 100644
--- a/doc/classes/TextMesh.xml
+++ b/doc/classes/TextMesh.xml
@@ -10,29 +10,6 @@
</description>
<tutorials>
</tutorials>
- <methods>
- <method name="clear_opentype_features">
- <return type="void" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code].
- </description>
- </method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="tag" type="String" />
- <argument index="1" name="value" type="int" />
- <description>
- Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
- </description>
- </method>
- </methods>
<members>
<member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5">
Step (in pixels) used to approximate Bézier curves.
@@ -41,7 +18,7 @@
Depths of the mesh, if set to [code]0.0[/code] only front surface, is generated, and UV layout is changed to use full texture for the front face only.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
- [Font] used for the [TextMesh]'s text.
+ Font configuration used to display text.
</member>
<member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
Font size of the [TextMesh]'s text.
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index aaaacfe3ac..6d615bd404 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -22,11 +22,10 @@
<method name="add_string">
<return type="bool" />
<argument index="0" name="text" type="String" />
- <argument index="1" name="fonts" type="Font" />
- <argument index="2" name="size" type="int" />
- <argument index="3" name="opentype_features" type="Dictionary" default="{}" />
- <argument index="4" name="language" type="String" default="&quot;&quot;" />
- <argument index="5" name="meta" type="Variant" default="null" />
+ <argument index="1" name="font" type="Font" />
+ <argument index="2" name="font_size" type="int" />
+ <argument index="3" name="language" type="String" default="&quot;&quot;" />
+ <argument index="4" name="meta" type="Variant" default="null" />
<description>
Adds text span and font to draw it.
</description>
@@ -217,18 +216,6 @@
Returns the size of the bounding box of the paragraph.
</description>
</method>
- <method name="get_spacing_bottom" qualifiers="const">
- <return type="int" />
- <description>
- Returns extra spacing at the bottom of the line. See [member Font.spacing_bottom].
- </description>
- </method>
- <method name="get_spacing_top" qualifiers="const">
- <return type="int" />
- <description>
- Returns extra spacing at the top of the line. See [member Font.spacing_top].
- </description>
- </method>
<method name="hit_test" qualifiers="const">
<return type="int" />
<argument index="0" name="coords" type="Vector2" />
@@ -256,11 +243,10 @@
<method name="set_dropcap">
<return type="bool" />
<argument index="0" name="text" type="String" />
- <argument index="1" name="fonts" type="Font" />
- <argument index="2" name="size" type="int" />
+ <argument index="1" name="font" type="Font" />
+ <argument index="2" name="font_size" type="int" />
<argument index="3" name="dropcap_margins" type="Rect2" default="Rect2(0, 0, 0, 0)" />
- <argument index="4" name="opentype_features" type="Dictionary" default="{}" />
- <argument index="5" name="language" type="String" default="&quot;&quot;" />
+ <argument index="4" name="language" type="String" default="&quot;&quot;" />
<description>
Sets drop cap, overrides previously set drop cap. Drop cap (dropped capital) is a decorative element at the beginning of a paragraph that is larger than the rest of the text.
</description>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index ca1aec19ea..4c8cf3982e 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -355,15 +355,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
- <method name="font_get_spacing" qualifiers="const">
- <return type="int" />
- <argument index="0" name="font_rid" type="RID" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
- <description>
- Returns extra spacing added between glyphs in pixels.
- </description>
- </method>
<method name="font_get_style" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -542,7 +533,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
- Removes specified texture from font cache entry.
+ Removes specified texture from the cache entry.
[b]Note:[/b] This function will not remove glyphs associated with the texture, remove them manually, using [method font_remove_glyph].
</description>
</method>
@@ -792,16 +783,6 @@
Adds override for [method font_is_script_supported].
</description>
</method>
- <method name="font_set_spacing">
- <return type="void" />
- <argument index="0" name="font_rid" type="RID" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
- <argument index="3" name="value" type="int" />
- <description>
- Sets extra spacing added between glyphs in pixels.
- </description>
- </method>
<method name="font_set_style">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -1286,6 +1267,14 @@
Returns size of the text.
</description>
</method>
+ <method name="shaped_text_get_spacing" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <description>
+ Returns extra spacing added between glyphs or lines in pixels.
+ </description>
+ </method>
<method name="shaped_text_get_trim_pos" qualifiers="const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
@@ -1431,6 +1420,15 @@
If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed.
</description>
</method>
+ <method name="shaped_text_set_spacing">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <argument index="2" name="value" type="int" />
+ <description>
+ Sets extra spacing added between glyphs or lines in pixels.
+ </description>
+ </method>
<method name="shaped_text_shape">
<return type="bool" />
<argument index="0" name="shaped" type="RID" />
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index b3be858ca1..2f7b31b663 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -345,15 +345,6 @@
Returns list of the font sizes in the cache. Each size is [code]Vector2i[/code] with font size and outline size.
</description>
</method>
- <method name="font_get_spacing" qualifiers="virtual const">
- <return type="int" />
- <argument index="0" name="font_rid" type="RID" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
- <description>
- Returns extra spacing added between glyphs in pixels.
- </description>
- </method>
<method name="font_get_style" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -531,7 +522,7 @@
<argument index="1" name="size" type="Vector2i" />
<argument index="2" name="texture_index" type="int" />
<description>
- Removes specified texture from font cache entry.
+ Removes specified texture from the cache entry.
</description>
</method>
<method name="font_render_glyph" qualifiers="virtual">
@@ -788,16 +779,6 @@
Adds override for [method font_is_script_supported].
</description>
</method>
- <method name="font_set_spacing" qualifiers="virtual">
- <return type="void" />
- <argument index="0" name="font_rid" type="RID" />
- <argument index="1" name="size" type="int" />
- <argument index="2" name="spacing" type="int" enum="TextServer.SpacingType" />
- <argument index="3" name="value" type="int" />
- <description>
- Sets extra spacing added between glyphs in pixels.
- </description>
- </method>
<method name="font_set_style" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -1288,6 +1269,14 @@
Returns size of the text.
</description>
</method>
+ <method name="shaped_text_get_spacing" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <description>
+ Returns extra spacing added between glyphs or lines in pixels.
+ </description>
+ </method>
<method name="shaped_text_get_trim_pos" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="shaped" type="RID" />
@@ -1436,6 +1425,15 @@
If set to [code]true[/code] text buffer will display invalid characters as hexadecimal codes, otherwise nothing is displayed.
</description>
</method>
+ <method name="shaped_text_set_spacing" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="shaped" type="RID" />
+ <argument index="1" name="spacing" type="int" enum="TextServer.SpacingType" />
+ <argument index="2" name="value" type="int" />
+ <description>
+ Sets extra spacing added between glyphs or lines in pixels.
+ </description>
+ </method>
<method name="shaped_text_shape" qualifiers="virtual">
<return type="bool" />
<argument index="0" name="shaped" type="RID" />
diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 5270da9588..7f4e0645c8 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -334,8 +334,8 @@
<argument index="0" name="name" type="StringName" />
<argument index="1" name="theme_type" type="StringName" />
<description>
- Returns [code]true[/code] if the font size property defined by [code]name[/code] and [code]theme_type[/code] exists, or if the default theme font size is set up (see [method has_default_font_size]).
- Returns [code]false[/code] if neither exist. Use [method set_font_size] to define the property.
+ Returns [code]true[/code] if [member default_font_size] has a valid value.
+ Returns [code]false[/code] if it doesn't. The value must be greater than [code]0[/code] to be considered valid.
</description>
</method>
<method name="has_icon" qualifiers="const">
@@ -426,8 +426,8 @@
<argument index="1" name="name" type="StringName" />
<argument index="2" name="theme_type" type="StringName" />
<description>
- Renames the font size property defined by [code]old_name[/code] and [code]theme_type[/code] to [code]name[/code], if it exists.
- Fails if it doesn't exist, or if a similar property with the new name already exists. Use [method has_font_size] to check for existence, and [method clear_font_size] to remove the existing property.
+ Returns [code]true[/code] if the font size property defined by [code]name[/code] and [code]theme_type[/code] exists, or if the default theme font size is set up (see [method has_default_font_size]).
+ Returns [code]false[/code] if neither exist. Use [method set_font_size] to define the property.
</description>
</method>
<method name="rename_icon">
@@ -495,7 +495,8 @@
<argument index="1" name="theme_type" type="StringName" />
<argument index="2" name="font_size" type="int" />
<description>
- Creates or changes the value of the font size property defined by [code]name[/code] and [code]theme_type[/code]. Use [method clear_font_size] to remove the property.
+ Renames the font size property defined by [code]old_name[/code] and [code]theme_type[/code] to [code]name[/code], if it exists.
+ Fails if it doesn't exist, or if a similar property with the new name already exists. Use [method has_font_size] to check for existence, and [method clear_font_size] to remove the existing property.
</description>
</method>
<method name="set_icon">
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 8a30364ebe..b06be0cf99 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -42,13 +42,6 @@
Clears the tree. This removes all items.
</description>
</method>
- <method name="clear_column_title_opentype_features">
- <return type="void" />
- <argument index="0" name="column" type="int" />
- <description>
- Removes all OpenType features from the item's text.
- </description>
- </method>
<method name="create_item">
<return type="TreeItem" />
<argument index="0" name="parent" type="TreeItem" default="null" />
@@ -114,14 +107,6 @@
Returns column title language code.
</description>
</method>
- <method name="get_column_title_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="column" type="int" />
- <argument index="1" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code] of the column title.
- </description>
- </method>
<method name="get_column_width" qualifiers="const">
<return type="int" />
<argument index="0" name="column" type="int" />
@@ -308,15 +293,6 @@
Sets language code of column title used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</description>
</method>
- <method name="set_column_title_opentype_feature">
- <return type="void" />
- <argument index="0" name="column" type="int" />
- <argument index="1" name="tag" type="String" />
- <argument index="2" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code] for the column title.
- </description>
- </method>
</methods>
<members>
<member name="allow_reselect" type="bool" setter="set_allow_reselect" getter="get_allow_reselect" default="false">
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index 0a680b9627..fbba1147a2 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -42,13 +42,6 @@
Resets the color for the given column to default.
</description>
</method>
- <method name="clear_opentype_features">
- <return type="void" />
- <argument index="0" name="column" type="int" />
- <description>
- Removes all OpenType features.
- </description>
- </method>
<method name="create_child">
<return type="TreeItem" />
<argument index="0" name="idx" type="int" default="-1" />
@@ -230,25 +223,17 @@
<method name="get_next" qualifiers="const">
<return type="TreeItem" />
<description>
- Returns the next TreeItem in the tree or a null object if there is none.
+ Returns the next sibling TreeItem in the tree or a null object if there is none.
</description>
</method>
<method name="get_next_visible">
<return type="TreeItem" />
<argument index="0" name="wrap" type="bool" default="false" />
<description>
- Returns the next visible TreeItem in the tree or a null object if there is none.
+ Returns the next visible sibling TreeItem in the tree or a null object if there is none.
If [code]wrap[/code] is enabled, the method will wrap around to the first visible element in the tree when called on the last visible element, otherwise it returns [code]null[/code].
</description>
</method>
- <method name="get_opentype_feature" qualifiers="const">
- <return type="int" />
- <argument index="0" name="column" type="int" />
- <argument index="1" name="tag" type="String" />
- <description>
- Returns OpenType feature [code]tag[/code] of the item's text.
- </description>
- </method>
<method name="get_parent" qualifiers="const">
<return type="TreeItem" />
<description>
@@ -258,14 +243,14 @@
<method name="get_prev">
<return type="TreeItem" />
<description>
- Returns the previous TreeItem in the tree or a null object if there is none.
+ Returns the previous sibling TreeItem in the tree or a null object if there is none.
</description>
</method>
<method name="get_prev_visible">
<return type="TreeItem" />
<argument index="0" name="wrap" type="bool" default="false" />
<description>
- Returns the previous visible TreeItem in the tree or a null object if there is none.
+ Returns the previous visible sibling TreeItem in the tree or a null object if there is none.
If [code]wrap[/code] is enabled, the method will wrap around to the last visible element in the tree when called on the first visible element, otherwise it returns [code]null[/code].
</description>
</method>
@@ -580,15 +565,6 @@
Sets the metadata value for the given column, which can be retrieved later using [method get_metadata]. This can be used, for example, to store a reference to the original data.
</description>
</method>
- <method name="set_opentype_feature">
- <return type="void" />
- <argument index="0" name="column" type="int" />
- <argument index="1" name="tag" type="String" />
- <argument index="2" name="value" type="int" />
- <description>
- Sets OpenType feature [code]tag[/code] for the item's text.
- </description>
- </method>
<method name="set_range">
<return type="void" />
<argument index="0" name="column" type="int" />
diff --git a/doc/classes/VideoStreamPlayer.xml b/doc/classes/VideoStreamPlayer.xml
index 092a754a39..f6594ff9e7 100644
--- a/doc/classes/VideoStreamPlayer.xml
+++ b/doc/classes/VideoStreamPlayer.xml
@@ -58,7 +58,7 @@
<member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="&amp;&quot;Master&quot;">
Audio bus to use for sound playback.
</member>
- <member name="expand" type="bool" setter="set_expand" getter="has_expand" default="true">
+ <member name="expand" type="bool" setter="set_expand" getter="has_expand" default="false">
If [code]true[/code], the video scales to the control size. Otherwise, the control minimum size will be automatically adjusted to match the video stream's dimensions.
</member>
<member name="paused" type="bool" setter="set_paused" getter="is_paused" default="false">
diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml
index 55ba1c4934..d941185d33 100644
--- a/doc/classes/VoxelGI.xml
+++ b/doc/classes/VoxelGI.xml
@@ -37,6 +37,7 @@
</member>
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(10, 10, 10)">
The size of the area covered by the [VoxelGI]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting.
+ [b]Note:[/b] Extents are clamped to 1.0 unit or more on each axis.
</member>
<member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" enum="VoxelGI.Subdiv" default="1">
Number of times to subdivide the grid that the [VoxelGI] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance.
diff --git a/doc/classes/XMLParser.xml b/doc/classes/XMLParser.xml
index c40a07c40a..79ab33045f 100644
--- a/doc/classes/XMLParser.xml
+++ b/doc/classes/XMLParser.xml
@@ -32,7 +32,7 @@
<method name="get_current_line" qualifiers="const">
<return type="int" />
<description>
- Gets the current line in the parsed file (currently not implemented).
+ Gets the current line in the parsed file, counting from 0.
</description>
</method>
<method name="get_named_attribute_value" qualifiers="const">
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index ce09361dfa..312dffc7ee 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -36,6 +36,7 @@ BASE_STRINGS = [
"Signals",
"Enumerations",
"Constants",
+ "Annotations",
"Property Descriptions",
"Constructor Descriptions",
"Method Descriptions",
@@ -122,16 +123,18 @@ class MethodDef:
class ConstantDef:
- def __init__(self, name, value, text): # type: (str, str, Optional[str]) -> None
+ def __init__(self, name, value, text, bitfield): # type: (str, str, Optional[str], Optional[bool]) -> None
self.name = name
self.value = value
self.text = text
+ self.is_bitfield = bitfield
class EnumDef:
- def __init__(self, name): # type: (str) -> None
+ def __init__(self, name, bitfield): # type: (str, Optional[bool]) -> None
self.name = name
self.values = OrderedDict() # type: OrderedDict[str, ConstantDef]
+ self.is_bitfield = bitfield
class ThemeItemDef:
@@ -155,6 +158,7 @@ class ClassDef:
self.methods = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
self.operators = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
self.signals = OrderedDict() # type: OrderedDict[str, SignalDef]
+ self.annotations = OrderedDict() # type: OrderedDict[str, List[MethodDef]]
self.theme_items = OrderedDict() # type: OrderedDict[str, ThemeItemDef]
self.inherits = None # type: Optional[str]
self.brief_description = None # type: Optional[str]
@@ -305,7 +309,8 @@ class State:
constant_name = constant.attrib["name"]
value = constant.attrib["value"]
enum = constant.get("enum")
- constant_def = ConstantDef(constant_name, value, constant.text)
+ is_bitfield = constant.get("is_bitfield") or False
+ constant_def = ConstantDef(constant_name, value, constant.text, is_bitfield)
if enum is None:
if constant_name in class_def.constants:
print_error('{}.xml: Duplicate constant "{}".'.format(class_name, constant_name), self)
@@ -318,11 +323,32 @@ class State:
enum_def = class_def.enums[enum]
else:
- enum_def = EnumDef(enum)
+ enum_def = EnumDef(enum, is_bitfield)
class_def.enums[enum] = enum_def
enum_def.values[constant_name] = constant_def
+ annotations = class_root.find("annotations")
+ if annotations is not None:
+ for annotation in annotations:
+ assert annotation.tag == "annotation"
+
+ annotation_name = annotation.attrib["name"]
+ qualifiers = annotation.get("qualifiers")
+
+ params = parse_arguments(annotation)
+
+ desc_element = annotation.find("description")
+ annotation_desc = None
+ if desc_element is not None:
+ annotation_desc = desc_element.text
+
+ annotation_def = MethodDef(annotation_name, return_type, params, annotation_desc, qualifiers)
+ if annotation_name not in class_def.annotations:
+ class_def.annotations[annotation_name] = []
+
+ class_def.annotations[annotation_name].append(annotation_def)
+
signals = class_root.find("signals")
if signals is not None:
for signal in signals:
@@ -706,7 +732,11 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
for value in e.values.values():
f.write(".. _class_{}_constant_{}:\n\n".format(class_name, value.name))
- f.write("enum **{}**:\n\n".format(e.name))
+ if e.is_bitfield:
+ f.write("flags **{}**:\n\n".format(e.name))
+ else:
+ f.write("enum **{}**:\n\n".format(e.name))
+
for value in e.values.values():
f.write("- **{}** = **{}**".format(value.name, value.value))
if value.text is not None and value.text.strip() != "":
@@ -732,6 +762,26 @@ def make_rst_class(class_def, state, dry_run, output_dir): # type: (ClassDef, S
f.write("\n\n")
+ if len(class_def.annotations) > 0:
+ f.write(make_heading("Annotations", "-"))
+ index = 0
+
+ for method_list in class_def.annotations.values():
+ for i, m in enumerate(method_list):
+ if index != 0:
+ f.write("----\n\n")
+
+ if i == 0:
+ f.write(".. _class_{}_annotation_{}:\n\n".format(class_name, m.name.strip("@")))
+
+ ret_type, signature = make_method_signature(class_def, m, "", state)
+ f.write("- {} {}\n\n".format(ret_type, signature))
+
+ if m.description is not None and m.description.strip() != "":
+ f.write(rstize_text(m.description.strip(), state) + "\n\n")
+
+ index += 1
+
# Property descriptions
if any(not p.overrides for p in class_def.properties.values()) > 0:
f.write(make_heading("Property Descriptions", "-"))
@@ -1065,6 +1115,11 @@ def rstize_text(text, state): # type: (str, State) -> str
print_error('{}.xml: Unresolved signal "{}".'.format(state.current_class, param), state)
ref_type = "_signal"
+ elif cmd.startswith("annotation"):
+ if method_param not in class_def.annotations:
+ print_error('{}.xml: Unresolved annotation "{}".'.format(state.current_class, param), state)
+ ref_type = "_annotation"
+
elif cmd.startswith("constant"):
found = False
diff --git a/doc/translations/ar.po b/doc/translations/ar.po
index dcfbccb71c..b21374a37f 100644
--- a/doc/translations/ar.po
+++ b/doc/translations/ar.po
@@ -12308,10 +12308,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19607,13 +19609,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19623,7 +19629,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19640,23 +19650,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30018,7 +30028,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30592,10 +30605,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30919,6 +30933,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36350,7 +36369,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36463,6 +36482,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50081,8 +50108,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58455,7 +58482,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59052,9 +59103,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60599,6 +60652,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "ÙŠÙØ±Ø¬Ø¹ جيب التمام \"cosine \" لقيمة المَعلم."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66687,9 +66745,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66718,7 +66777,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ca.po b/doc/translations/ca.po
index 8576fd5bf3..0e33b91074 100644
--- a/doc/translations/ca.po
+++ b/doc/translations/ca.po
@@ -12252,10 +12252,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19537,13 +19539,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19553,7 +19559,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19570,23 +19580,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29935,7 +29945,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30509,10 +30522,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30835,6 +30849,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36235,7 +36254,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36346,6 +36365,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49925,8 +49952,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58295,7 +58322,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58892,9 +58943,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60431,6 +60484,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66505,9 +66562,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66536,7 +66594,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot
index dba0a87744..8d833031fe 100644
--- a/doc/translations/classes.pot
+++ b/doc/translations/classes.pot
@@ -12132,10 +12132,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19417,13 +19419,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19433,7 +19439,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19450,23 +19460,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29812,7 +29822,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30386,10 +30399,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30712,6 +30726,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36112,7 +36131,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36223,6 +36242,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49802,8 +49829,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58172,7 +58199,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58769,9 +58820,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60308,6 +60361,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66382,9 +66439,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66413,7 +66471,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/cs.po b/doc/translations/cs.po
index e6d0fc8c49..85a9d50b28 100644
--- a/doc/translations/cs.po
+++ b/doc/translations/cs.po
@@ -12653,10 +12653,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19985,13 +19987,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20001,7 +20007,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20018,23 +20028,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30408,7 +30418,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30982,10 +30995,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31309,6 +31323,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36749,7 +36768,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36862,6 +36881,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50499,8 +50526,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58889,7 +58916,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59486,9 +59537,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61043,6 +61096,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Vrátí [code] true [/code], pokud je vektor normalizován, jinak false."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67164,9 +67222,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67195,7 +67254,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/de.po b/doc/translations/de.po
index 14a4d14da6..ae8d8f2165 100644
--- a/doc/translations/de.po
+++ b/doc/translations/de.po
@@ -14222,10 +14222,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -21703,13 +21705,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -21719,7 +21725,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -21736,23 +21746,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -32199,7 +32209,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -32773,10 +32786,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -33104,6 +33118,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -38619,7 +38638,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -38734,6 +38753,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -52484,8 +52511,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -60981,7 +61008,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -61582,9 +61633,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -63158,6 +63211,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Wenn [code]true[/code], wird die Textur zentriert."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -69471,9 +69529,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -69505,7 +69564,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/el.po b/doc/translations/el.po
index 782205fcfa..d3cbf69925 100644
--- a/doc/translations/el.po
+++ b/doc/translations/el.po
@@ -12152,10 +12152,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19452,13 +19454,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19468,7 +19474,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19485,23 +19495,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29863,7 +29873,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30437,10 +30450,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30764,6 +30778,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36189,7 +36208,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36302,6 +36321,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49907,8 +49934,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58281,7 +58308,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58878,9 +58929,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60425,6 +60478,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "ΕπιστÏέφει το συνημίτονο της παÏαμέτÏου."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66513,9 +66571,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66544,7 +66603,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/es.po b/doc/translations/es.po
index 242710fe39..e38eb521c0 100644
--- a/doc/translations/es.po
+++ b/doc/translations/es.po
@@ -15915,10 +15915,12 @@ msgstr ""
"horizontales y el tamaño de la pantalla."
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr "La cámara se actualiza con la llamada [code]_physics_process[/code]."
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr "La cámara se actualiza con la llamada de [code]_process[/code]."
@@ -25571,16 +25573,18 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
-"Si [code]true[/code], el detalle de la sombra se sacrifica a cambio de "
-"transiciones más suaves entre las divisiones."
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -25591,8 +25595,12 @@ msgstr ""
"movimiento. Ver [enum ShadowDepthRange]."
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
-msgstr "La distancia máxima para las divisiones de la sombra."
+msgid ""
+"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)."
+msgstr ""
#: doc/classes/DirectionalLight.xml
msgid "The light's shadow rendering algorithm. See [enum ShadowMode]."
@@ -25606,11 +25614,12 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"La distancia de la cámara a la sombra se divide en 1. Relativo a [member "
"directional_shadow_max_distance]. Sólo se utiliza cuando [member "
@@ -25618,11 +25627,12 @@ msgstr ""
"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"La distancia de la sombra se divide en dos. Relativo a [member "
"directional_shadow_max_distance]. Sólo se utiliza cuando [member "
@@ -25630,10 +25640,11 @@ msgstr ""
"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"La distancia de la sombra se divide en dos y tres. Relativo a [member "
"directional_shadow_max_distance]. Sólo se usa cuando [member "
@@ -39542,7 +39553,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
"Habilita o deshabilita la acumulación de eventos de entrada similares "
"enviados por el sistema operativo. Cuando la acumulación de entrada está "
@@ -40301,10 +40315,11 @@ msgstr "Tipo de evento de entrada para los eventos de movimiento del ratón."
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -40745,6 +40760,12 @@ msgstr ""
"automáticamente el nuevo contenido."
#: doc/classes/InterpolatedCamera.xml
+#, fuzzy
+msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr "La llamada al proceso de la cámara. Ver [enum Camera2DProcessMode]."
+
+#: doc/classes/InterpolatedCamera.xml
msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
@@ -47706,7 +47727,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -47821,6 +47842,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -65718,12 +65747,13 @@ msgstr ""
"documentación del mapeo de sombras."
#: doc/classes/ProjectSettings.xml
+#, fuzzy
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
-"Tamaño para el atlas de sombras (usado para OmniLights y SpotLights). Vea la "
-"documentación."
+"Establece el tamaño de las imágenes del atlas de sombras (usado para omni y "
+"focos). El valor se redondeará a la potencia más cercana de 2."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -76413,10 +76443,32 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
-"Formatea la string reemplazando todas las ocurrencias de [code]placeholder[/"
-"code] por [code]values[/code]."
#: doc/classes/String.xml
msgid "If the string is a valid file path, returns the base directory name."
@@ -77186,13 +77238,12 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
-"Dibuja este cuadro de estilo usando un [CanvasItem] con un [RID] dado.\n"
-"Puedes obtener un valor [RID] usando el [method Object.get_instance_id] en "
-"un nodo derivado de [CanvasItem]."
#: doc/classes/StyleBox.xml
msgid "Returns the size of this [StyleBox] without the margins."
@@ -79173,6 +79224,11 @@ msgstr ""
"contextual."
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Si [code]true[/code], el cuerpo puede ser detectado por los rayos."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -87155,12 +87211,14 @@ msgstr ""
"La cantidad de subdivisión del cuarto cuadrante en el atlas de las sombras."
#: doc/classes/Viewport.xml
+#, fuzzy
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
"La resolución del atlas de las sombras (usado para luces omni y spot). El "
"valor se redondeará a la potencia más cercana de 2.\n"
@@ -87197,9 +87255,12 @@ msgid ""
msgstr "Si [code]true[/code], el viewport debería hacer su fondo transparente."
#: doc/classes/Viewport.xml
-#, fuzzy
-msgid "The rendering mode of viewport."
-msgstr "El modo de selección a utilizar."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
+msgstr ""
#: doc/classes/Viewport.xml
msgid ""
diff --git a/doc/translations/fa.po b/doc/translations/fa.po
index a8972b49a5..db8018d209 100644
--- a/doc/translations/fa.po
+++ b/doc/translations/fa.po
@@ -12573,10 +12573,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19858,13 +19860,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19874,7 +19880,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19891,23 +19901,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30256,7 +30266,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30830,10 +30843,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31156,6 +31170,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36562,7 +36581,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36673,6 +36692,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50264,8 +50291,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58638,7 +58665,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59235,9 +59286,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60774,6 +60827,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66848,9 +66905,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66879,7 +66937,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/fi.po b/doc/translations/fi.po
index 9c41935f5e..9317c255a7 100644
--- a/doc/translations/fi.po
+++ b/doc/translations/fi.po
@@ -12226,10 +12226,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19528,13 +19530,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19544,7 +19550,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19561,23 +19571,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29946,7 +29956,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30520,10 +30533,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30847,6 +30861,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36274,7 +36293,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36387,6 +36406,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49992,8 +50019,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58368,7 +58395,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58965,9 +59016,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60513,6 +60566,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Palauttaa parametrin kosinin."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66606,9 +66664,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66637,7 +66696,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/fil.po b/doc/translations/fil.po
index 1ae1d0b02b..f7a8c0fd9b 100644
--- a/doc/translations/fil.po
+++ b/doc/translations/fil.po
@@ -12148,10 +12148,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19433,13 +19435,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19449,7 +19455,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19466,23 +19476,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29831,7 +29841,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30405,10 +30418,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30731,6 +30745,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36131,7 +36150,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36242,6 +36261,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49821,8 +49848,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58191,7 +58218,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58788,9 +58839,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60327,6 +60380,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66401,9 +66458,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66432,7 +66490,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/fr.po b/doc/translations/fr.po
index 2dcac4940b..7b3d3c7435 100644
--- a/doc/translations/fr.po
+++ b/doc/translations/fr.po
@@ -61,7 +61,7 @@ msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2022-06-28 04:52+0000\n"
+"PO-Revision-Date: 2022-07-06 04:47+0000\n"
"Last-Translator: Maxime Leroy <lisacintosh@gmail.com>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/fr/>\n"
@@ -985,7 +985,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two values by the factor defined in "
"[code]weight[/code]. To perform interpolation, [code]weight[/code] should be "
@@ -1005,13 +1004,16 @@ msgid ""
"To perform eased interpolation with [method lerp], combine it with [method "
"ease] or [method smoothstep]."
msgstr ""
-"Interpolation linéaire entre deux valeurs par une valeur normalisée. C'est "
-"l'inverse de [method inverse_lerp].\n"
+"L'interpolation linéaire entre deux valeurs avec un facteur défini par "
+"[code]weight[/code]. Pour faire une interpolation, [code]weight[/code] doit "
+"être entre [code]0.0[/code] et [code]1.0[/code] (inclus). Pour autant, des "
+"valeurs en dehors de cet intervalle sont autorisés pour faire une "
+"[i]extrapolation[/i].\n"
"Si les arguments [code]from[/code] et [code]to[/code] sont de type [int] ou "
-"[float], la valeur de retour est un [float].\n"
+"[float], la valeur retournée est un [float].\n"
"Si les deux sont du même type de vecteur ([Vector2], [Vector3] ou [Color]), "
-"la valeur de retour sera du même type ([code]lerp[/code] appelle alors la "
-"méthode du type de vecteur [code]linear_interpolate[/code]).\n"
+"la valeur de retour sera du même type (puisque [code]lerp[/code] appelle "
+"alors la méthode [code]linear_interpolate[/code] du même type).\n"
"[codeblock]\n"
"lerp(0, 4, 0.75) # Retourne 3.0\n"
"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Retourne Vector2(2, 3.5)\n"
@@ -4060,6 +4062,10 @@ msgid ""
"down on the key after it \"bottoms out\". This message is different from "
"polyphonic after-touch as it indicates the highest pressure across all keys."
msgstr ""
+"Le message de pression de canal MIDI. Ce message est le plus souvent envoyé "
+"en appuyant sur la touche après qu'il « se retire » . Ce message est "
+"différent de l'après-touche polyphonique car il indique la plus haute "
+"pression sur toutes les clés."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4074,6 +4080,9 @@ msgid ""
"MIDI system exclusive message. This has behavior exclusive to the device "
"you're receiving input from. Getting this data is not implemented in Godot."
msgstr ""
+"Le message exclusif du système MIDI. Cela a un comportement exclusif à "
+"l'appareil dont vous recevez l'entrée. Obtenir cette donnée n'est pas "
+"implémenté dans Godot."
#: doc/classes/@GlobalScope.xml
msgid ""
@@ -4086,30 +4095,43 @@ msgid ""
"MIDI song position pointer message. Gives the number of 16th notes since the "
"start of the song. Getting this data is not implemented in Godot."
msgstr ""
+"Le message de position de chanson MIDI. Donne le nombre de seizième de note "
+"depuis le début de la chanson. Obtenir cette donnée n'est pas implémenté "
+"dans Godot."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI song select message. Specifies which sequence or song is to be played. "
"Getting this data is not implemented in Godot."
msgstr ""
+"Le message de sélectionne de la chanson. Spécifie quelle séquence ou quelle "
+"chanson doit être jouée. Obtenir cette donnée n'est pas implémenté dans "
+"Godot."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI tune request message. Upon receiving a tune request, all analog "
"synthesizers should tune their oscillators."
msgstr ""
+"Le message de requête d'accordage MIDI. À la réception d'une requête "
+"d'accordage, tous les synthétiseurs analogiques devraient accorder leurs "
+"oscillateurs."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI timing clock message. Sent 24 times per quarter note when "
"synchronization is required."
msgstr ""
+"Le message d'horloge MIDI. Envoyé 24 fois par quart de note lorsque la "
+"synchronisation est requise."
#: doc/classes/@GlobalScope.xml
msgid ""
"MIDI start message. Start the current sequence playing. This message will be "
"followed with Timing Clocks."
msgstr ""
+"Le message de démarrage MIDI. Commence la séquence actuelle. Ce message sera "
+"suivi avec un message d'horloge."
#: doc/classes/@GlobalScope.xml
msgid "MIDI continue message. Continue at the point the sequence was stopped."
@@ -5206,7 +5228,6 @@ msgstr ""
"entrée, le dialogue sera accepté."
#: doc/classes/AcceptDialog.xml
-#, fuzzy
msgid ""
"Removes the [code]button[/code] from the dialog. Does NOT free the "
"[code]button[/code]. The [code]button[/code] must be a [Button] added with "
@@ -5214,9 +5235,11 @@ msgid ""
"the [code]button[/code] will no longer emit this dialog's [signal "
"custom_action] signal or cancel this dialog."
msgstr ""
-"Enlever le [code]bouton[/code] de la boite de la boîte de dialogue. Ne "
-"libère PAS le bouton. Le bouton dois être un [Button] ajouté avec la méthode "
-"[method add_button] ou [method add_cancel] ."
+"Retire le [code]button[/code] de la boite de dialogue. Ne libère PAS le "
+"[code]button[/code]. Le [code]button[/code] doit être un [Button] ajouté "
+"avec la méthode [method add_button] ou [method add_cancel]. Après être "
+"retiré, appuyer sur [code]button[/code] n'émettra plus le signal [signal "
+"custom_action] du dialogue ni ne l'annulera."
#: doc/classes/AcceptDialog.xml
msgid "Sets autowrapping for the text in the dialog."
@@ -8408,6 +8431,10 @@ msgid ""
"binds animations to animation nodes.\n"
"Once set, [Animation] nodes can be added to the [AnimationTreePlayer]."
msgstr ""
+"Le chemin vers le [AnimationPlayer] d'où cette [AnimationTreePlayer] "
+"connecte les animations aux nœuds d'animation.\n"
+"Une fois défini, les nœuds [Animation] peuvent être ajoutés au "
+"[AnimationTreePlayer]."
#: doc/classes/AnimationTreePlayer.xml
msgid "The thread in which to update animations."
@@ -8592,6 +8619,10 @@ msgid ""
"See [member ProjectSettings.physics/3d/default_linear_damp] for more details "
"about damping."
msgstr ""
+"La vitesse à laquelle les objets arrêtent de se déplacer dans cette zone. "
+"Représente la vitesse linéaire perdue par seconde.\n"
+"Voir [member ProjectSettings.physics/3d/default_linear_damp] pour plus de "
+"détails sur l'amortissement."
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid "If [code]true[/code], other monitoring areas can detect this area."
@@ -10832,6 +10863,9 @@ msgid ""
"the AR/VR eyes to [VisualServer]. The value comes from an internal call to "
"[method OS.get_ticks_usec]."
msgstr ""
+"Retourne l'horodatage absolu (en μs) de la dernière mise à jour des yeux AR/"
+"VR du [ARVRServer] envoyée au [VisualServer]. La valeur est récupérée via un "
+"appel interne à [method OS.get_ticks_usec]"
#: doc/classes/ARVRServer.xml
msgid ""
@@ -10839,6 +10873,9 @@ msgid ""
"difference between [method get_last_commit_usec] and [method "
"get_last_process_usec] when committing."
msgstr ""
+"Retourne la durée (en μs) de la dernière trame. Ceci est calculé comme la "
+"différence entre [method get_last_commit_usec] et [method "
+"get_last_process_usec] lorsque vous commettez."
#: doc/classes/ARVRServer.xml
msgid ""
@@ -10846,6 +10883,9 @@ msgid ""
"callback. The value comes from an internal call to [method OS."
"get_ticks_usec]."
msgstr ""
+"Retourne l'horodatage absolu (en μs) du dernier appel de mise à jour du "
+"[ARVRServer]. La valeur vient est récupérée via un appel interne à [method "
+"OS.get_ticks_usec]"
#: doc/classes/ARVRServer.xml
msgid ""
@@ -12137,6 +12177,8 @@ msgid ""
"High-pass filter, in Hz. Frequencies higher than this value will not be "
"affected by the distortion. Value can range from 1 to 20000."
msgstr ""
+"Le filtre passe-haut, en Hz. Les fréquences supérieures à cette valeur ne "
+"seront pas affectées par la distorsion. La valeur peut aller de 1 à 20000 Hz."
#: doc/classes/AudioEffectDistortion.xml
msgid "Distortion type."
@@ -12147,12 +12189,16 @@ msgid ""
"Increases or decreases the volume after the effect. Value can range from -80 "
"to 24."
msgstr ""
+"Augmente ou diminue le volume sonore après l'application de l'effet. La "
+"valeur peut aller de -80 à 24 dB."
#: doc/classes/AudioEffectDistortion.xml
msgid ""
"Increases or decreases the volume before the effect. Value can range from "
"-60 to 60."
msgstr ""
+"Augmente ou diminue le volume sonore avant l'application de l'effet. La "
+"valeur peut aller de -60 à 60 dB."
#: doc/classes/AudioEffectDistortion.xml
msgid ""
@@ -12165,6 +12211,8 @@ msgid ""
"Low-resolution digital distortion effect. You can use it to emulate the "
"sound of early digital audio devices."
msgstr ""
+"Effet de distorsion numérique à basse résolution. Vous pouvez l'utiliser "
+"pour émuler le son des tous premiers périphériques audio numériques."
#: doc/classes/AudioEffectDistortion.xml
msgid ""
@@ -12530,6 +12578,10 @@ msgid ""
"are more demanding on the CPU and may cause audio cracking if the CPU can't "
"keep up."
msgstr ""
+"Le facteur de suréchantillonnage à utiliser. Des valeurs plus élevées "
+"entraînent une meilleure qualité, mais nécessitent plus de puissance du CPU "
+"et peuvent provoquer des craquements audibles si le CPU n'est pas assez "
+"puissant."
#: doc/classes/AudioEffectPitchShift.xml
msgid ""
@@ -12818,6 +12870,8 @@ msgid ""
"Returns the [AudioEffectInstance] assigned to the given bus and effect "
"indices (and optionally channel)."
msgstr ""
+"Retourne le [AudioEffectInstance] assigné au bus et aux indices de l'effet "
+"donnés (et le canal en option)."
#: doc/classes/AudioServer.xml
msgid "Returns the index of the bus with the name [code]bus_name[/code]."
@@ -12832,26 +12886,32 @@ msgid ""
"Returns the peak volume of the left speaker at bus index [code]bus_idx[/"
"code] and channel index [code]channel[/code]."
msgstr ""
+"Retourne le volume de crête du haut-parleur gauche à l'index du bus "
+"[code]bus_idx[/code] et l'index du canal [code]canal[/code]."
#: doc/classes/AudioServer.xml
msgid ""
"Returns the peak volume of the right speaker at bus index [code]bus_idx[/"
"code] and channel index [code]channel[/code]."
msgstr ""
+"Retourne le volume de crête du haut-parleur droit à l'index de bus "
+"[code]bus_idx[/code] et l'index de canal [code]canal[/code]."
#: doc/classes/AudioServer.xml
msgid ""
"Returns the name of the bus that the bus at index [code]bus_idx[/code] sends "
"to."
msgstr ""
+"Retourne le nom du bus vers lequel le bus à l'index [code]bus_idx[/code] "
+"envoie l'audio."
#: doc/classes/AudioServer.xml
msgid "Returns the volume of the bus at index [code]bus_idx[/code] in dB."
-msgstr ""
+msgstr "Retourne le volume du bus à l'index [code]bus_idx[/code] en dB."
#: doc/classes/AudioServer.xml
msgid "Returns the names of all audio devices detected on the system."
-msgstr ""
+msgstr "Retourne les noms de tous les appareils audio détectés sur le système."
#: doc/classes/AudioServer.xml
#, fuzzy
@@ -12887,6 +12947,8 @@ msgid ""
"If [code]true[/code], the effect at index [code]effect_idx[/code] on the bus "
"at index [code]bus_idx[/code] is enabled."
msgstr ""
+"Si [code]true[/code], l'effet à l'index [code]effect_idx[/code] sur le bus à "
+"l'index [code]bus_idx[/code] est activé."
#: doc/classes/AudioServer.xml
msgid "If [code]true[/code], the bus at index [code]bus_idx[/code] is muted."
@@ -12897,12 +12959,15 @@ msgstr ""
msgid ""
"If [code]true[/code], the bus at index [code]bus_idx[/code] is in solo mode."
msgstr ""
+"Si [code]true[/code], le bus à l'index [code]bus_idx[/code] est en mode solo."
#: doc/classes/AudioServer.xml
msgid ""
"Locks the audio driver's main loop.\n"
"[b]Note:[/b] Remember to unlock it afterwards."
msgstr ""
+"Verrouille la boucle principale du pilote audio.\n"
+"[b]Note :[/b] Il est important de la déverrouiller après utilisation."
#: doc/classes/AudioServer.xml
msgid ""
@@ -12930,6 +12995,7 @@ msgstr "Remplace le [AudioBusLayout] actuellement utilisé."
msgid ""
"Sets the name of the bus at index [code]bus_idx[/code] to [code]name[/code]."
msgstr ""
+"Définit le nom du bus à l'index [code]bus_idx[/code] avec [code]name[/code]."
#: doc/classes/AudioServer.xml
msgid ""
@@ -12944,6 +13010,8 @@ msgid ""
"Sets the volume of the bus at index [code]bus_idx[/code] to [code]volume_db[/"
"code]."
msgstr ""
+"Définit le volume du bus à l'index [code]bus_idx[/code] à [code]volume_db[/"
+"code]."
#: doc/classes/AudioServer.xml
msgid "Swaps the position of two effects in bus [code]bus_idx[/code]."
@@ -12954,6 +13022,8 @@ msgid ""
"Unlocks the audio driver's main loop. (After locking it, you should always "
"unlock it.)"
msgstr ""
+"Déverrouille la boucle principale du pilote audio. (Après le verrouillage, "
+"vous devriez toujours le déverrouiller.)"
#: doc/classes/AudioServer.xml
msgid "Number of available audio buses."
@@ -12998,6 +13068,8 @@ msgid ""
"Scales the rate at which audio is played (i.e. setting it to [code]0.5[/"
"code] will make the audio be played twice as fast)."
msgstr ""
+"Mets à l'échelle la fréquence à laquelle l'audio est joué (c'est-à-dire que "
+"la valeur [code]0.5[/code] jouera l'audio deux fois plus vite)."
#: doc/classes/AudioServer.xml
msgid "Emitted when the [AudioBusLayout] changes."
@@ -13029,6 +13101,9 @@ msgid ""
"music playback, and support WAV (via [AudioStreamSample]) and OGG (via "
"[AudioStreamOGGVorbis]) file formats."
msgstr ""
+"La classe de base pour les flux audio. Les flux audio sont utilisés pour les "
+"effets sonores et la lecture de musique, et supportent les formats de "
+"fichiers WAV (via [AudioStreamSample)] et OGG (via [AudioStreamOGGVorbis)]."
#: doc/classes/AudioStream.xml doc/classes/AudioStreamPlayer.xml
msgid "Audio streams"
@@ -13060,6 +13135,15 @@ msgid ""
"class from GDScript, consider using a lower [member mix_rate] such as 11,025 "
"Hz or 22,050 Hz."
msgstr ""
+"Ce flux audio ne joue pas de sons par défaut, les données audio doivent être "
+"générées à partir d'un script. Voir aussi [AudioStreamGeneratorPlayback].\n"
+"Voir aussi [AudioEffectSpectrumAnalyzer] pour l'analyse spectrale de l'audio "
+"en temps réel.\n"
+"[b]Note :[/b] En raison des contraintes de performance, il est préférable "
+"d'utiliser cette classe à partir de code C# ou d'un langage compilée via "
+"GDNative. Si vous souhaitez tout de même utiliser cette classe avec "
+"GDScript, envisagez d'utiliser une fréquence [member mix_rate] plus faible "
+"comme 11025 Hz ou 22050 Hz."
#: doc/classes/AudioStreamGenerator.xml
msgid ""
@@ -13068,6 +13152,11 @@ msgid ""
"resulting in increased CPU usage and more risk for audio cracking if the CPU "
"can't keep up."
msgstr ""
+"La longueur de la mémoire tampon à générer (en secondes). Les valeurs "
+"inférieures entraînent moins de latence, mais exigent que le script génère "
+"les données audio plus rapidement, ce qui entraîne une utilisation plus "
+"important du CPU et plus de risques de craquements audio si le CPU n'est pas "
+"assez puissant."
#: doc/classes/AudioStreamGenerator.xml
msgid ""
@@ -13130,6 +13219,11 @@ msgid ""
"added again. Therefore, make sure your script can always generate and push "
"new audio frames fast enough to avoid audio cracking."
msgstr ""
+"Retourne le nombre de frames de données audio restantes à jouer. Si ce "
+"nombre atteint [code]0[/code], l'audio cessera de jouer jusqu'à ce que de "
+"nouvelles frames soient ajoutés. Par conséquent, assurez-vous que votre "
+"script peut toujours générer et pousser de nouveaux frames audio assez "
+"rapidement pour éviter les craquements audio."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -13137,6 +13231,10 @@ msgid ""
"efficient than [method push_frame] in C# and compiled languages via "
"GDNative, but [method push_buffer] may be [i]less[/i] efficient in GDScript."
msgstr ""
+"Ajoute plusieurs frames de données audio dans la mémoire tampon. Ceci est "
+"généralement plus efficace que [method push_frame] pour le C# et les "
+"langages compilés avec GDNative, mais [method push_buffer] peut être "
+"[i]moins[/i] efficace avec GDScript."
#: doc/classes/AudioStreamGeneratorPlayback.xml
msgid ""
@@ -13144,6 +13242,10 @@ msgid ""
"efficient than [method push_buffer] in C# and compiled languages via "
"GDNative, but [method push_frame] may be [i]more[/i] efficient in GDScript."
msgstr ""
+"Ajouter une seule frame de données audio dans la mémoire tampon. Ceci est "
+"généralement moins efficace que [method push_buffer] pour le C# et les "
+"langages compilés avec GDNative, mais [method push_frame] peut être "
+"[i]moins[/i] efficace avec GDScript."
#: modules/minimp3/doc_classes/AudioStreamMP3.xml
#, fuzzy
@@ -13167,7 +13269,7 @@ msgstr ""
#: modules/minimp3/doc_classes/AudioStreamMP3.xml
#: modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
msgid "Time in seconds at which the stream starts after being looped."
-msgstr ""
+msgstr "Le temps en secondes où le flux commence après avoir bouclé."
#: modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
msgid "OGG Vorbis audio stream driver."
@@ -13182,6 +13284,8 @@ msgid ""
"Can play, loop, pause a scroll through audio. See [AudioStream] and "
"[AudioStreamOGGVorbis] for usage."
msgstr ""
+"Peut jouer, boucler, faire pause dans l'audio. Voir [AudioStream] et "
+"[AudioStreamOGGVorbis] pour l'utilisation."
#: doc/classes/AudioStreamPlayer.xml
msgid "Plays back audio non-positionally."
@@ -13193,6 +13297,9 @@ msgid ""
"To play audio positionally, use [AudioStreamPlayer2D] or "
"[AudioStreamPlayer3D] instead of [AudioStreamPlayer]."
msgstr ""
+"Joue un flux audio indépendamment de la position.\n"
+"Pour jouer audio en fonction de la position, utilisez [AudioStreamPlayer2D] "
+"ou [AudioStreamPlayer3D] au lieu de [AudioStreamPlayer]."
#: doc/classes/AudioStreamPlayer.xml
msgid "Returns the position in the [AudioStream] in seconds."
@@ -13281,6 +13388,7 @@ msgstr "L'audio sera joué sur tous les canaux surround."
msgid ""
"The audio will be played on the second channel, which is usually the center."
msgstr ""
+"L'audio sera joué sur le deuxième canal, qui est généralement le centre."
#: doc/classes/AudioStreamPlayer2D.xml
msgid "Plays positional sound in 2D space."
@@ -13295,6 +13403,13 @@ msgid ""
"[member volume_db] to a very low value like [code]-100[/code] (which isn't "
"audible to human hearing)."
msgstr ""
+"Joue l'audio étant amortit suivan la distance du centre d'écran.\n"
+"Voir aussi [AudioStreamPlayer] pour jouer un son indépendemment de la "
+"position.\n"
+"[b]Note :[/b] Masquer un nœud [AudioStreamPlayer2D] ne désactive pas sa "
+"sortie audio. Pour désactiver temporairement la sortie audio d'un "
+"[AudioStreamPlayer2D], choisissez une valeur très basse pour [member "
+"volume_db] comme [code]-100[/code] (qui n'est pas audible humainement)."
#: doc/classes/AudioStreamPlayer2D.xml doc/classes/AudioStreamPlayer3D.xml
msgid "Returns the position in the [AudioStream]."
@@ -13324,6 +13439,12 @@ msgid ""
"\"water\" area so that sounds played in the water are redirected through an "
"audio bus to make them sound like they are being played underwater."
msgstr ""
+"Détermine quelles calques du [Area2D] affectent le son pour les effets de "
+"réverbération et du bus audio. Les zones peuvent être utilisées pour "
+"rediriger le [AudioStream] afin qu'ils soient joués dans un certain bus "
+"audio. Un exemple de la façon dont vous pouvez utiliser ceci est de faire "
+"une zone \"eau\" de sorte que les sons joués dans l'eau sont redirigés par "
+"un bus audio pour les faire sonner comme ils étaient joués sous l'eau."
#: doc/classes/AudioStreamPlayer2D.xml
msgid "Dampens audio over distance with this as an exponent."
@@ -13399,6 +13520,10 @@ msgid ""
"disable the dampening effect entirely, set this to [code]20500[/code] as "
"this frequency is above the human hearing limit."
msgstr ""
+"Amortit l'audio en utilisant un filtre passe-bas au-dessus de la fréquence "
+"spécifiée, en Hz. Pour désactiver entièrement l'effet d'amortissement, "
+"définissez la fréquence à [code]20500[/code] car cette fréquence est "
+"supérieure à la limite de l'audition humaine."
#: doc/classes/AudioStreamPlayer3D.xml
msgid "Amount how much the filter affects the loudness, in decibels."
@@ -13579,6 +13704,13 @@ msgid ""
"This class can also be used to store dynamically-generated PCM audio data. "
"See also [AudioStreamGenerator] for procedural audio generation."
msgstr ""
+"AudioStreamSample stocke des échantillons sonores chargés depuis des "
+"fichiers WAV. Pour jouer le son enregistré, utilisez un [AudioStreamPlayer] "
+"(pour l'audio indépendamment de la position) ou AudioStreamPlayer2D]/"
+"[AudioStreamPlayer3D (en fonction de la position). Le son peut être bouclé.\n"
+"Cette classe peut également être utilisée pour stocker des données audio "
+"dynamiques au format PCM. Voir aussi [AudioStreamGenerator] pour la "
+"génération audio procédurale."
#: doc/classes/AudioStreamSample.xml
msgid ""
@@ -13587,6 +13719,11 @@ msgid ""
"[b]Note:[/b] A [code].wav[/code] extension is automatically appended to "
"[code]path[/code] if it is missing."
msgstr ""
+"Enregistre le AudioStreamSample dans un fichier WAV à l'emplacement "
+"[code]path[/code]. Les échantillons au format IMA ADPCM peuvent être "
+"enregistrés.\n"
+"[b]Note :[/b] L'extension [code].wav[/code] est automatiquement ajoutée au "
+"[code]path[/code] si elle manque."
#: doc/classes/AudioStreamSample.xml
msgid ""
@@ -13594,6 +13731,10 @@ msgid ""
"[b]Note:[/b] This property expects signed PCM8 data. To convert unsigned "
"PCM8 to signed PCM8, subtract 128 from each byte."
msgstr ""
+"Contient les données audio en octets.\n"
+"[b]Note :[/b] Cette propriété s'attend à des données PCM8 signées. Pour "
+"convertir des PCM8 non signés en PCM8, il faut soustraire 128 de chaque "
+"octet."
#: doc/classes/AudioStreamSample.xml
msgid "Audio format. See [enum Format] constants for values."
@@ -13607,6 +13748,9 @@ msgid ""
"sample). This information will be imported automatically from the WAV file "
"if present."
msgstr ""
+"Le point de départ de la boucle (en nombre de frames depuis le début de "
+"l'échantillon). Ces informations seront automatiquement importées depuis le "
+"fichier WAV si elles y sont présentes."
#: doc/classes/AudioStreamSample.xml
msgid ""
@@ -13614,12 +13758,18 @@ msgid ""
"sample). This information will be imported automatically from the WAV file "
"if present."
msgstr ""
+"Le point de fin de la boucle (en nombre de frames depuis le début de "
+"l'échantillon). Ces informations seront automatiquement importées depuis le "
+"fichier WAV si elles y sont présentes."
#: doc/classes/AudioStreamSample.xml
msgid ""
"The loop mode. This information will be imported automatically from the WAV "
"file if present. See [enum LoopMode] constants for values."
msgstr ""
+"Le mode de boucle. Ces informations seront automatiquement importées depuis "
+"fichier WAV si elles y sont présentes. Voir les constantes [enum LoopMode] "
+"pour les valeurs possibles."
#: doc/classes/AudioStreamSample.xml
msgid ""
@@ -13683,6 +13833,8 @@ msgid ""
"Audio loops the data between [member loop_begin] and [member loop_end], "
"playing back and forth."
msgstr ""
+"Les données audio bouclent entre [member loop_begin] et [member loop_end], "
+"jouant en arrière puis en avant."
#: doc/classes/AudioStreamSample.xml
msgid ""
@@ -13698,6 +13850,9 @@ msgid ""
"accessed in your shader scripts through the "
"[code]texture(SCREEN_TEXTURE, ...)[/code] function."
msgstr ""
+"Copie une région de l'écran (ou l'écran entier) vers une mémoire tampon afin "
+"qu'il puisse être accédé dans vos shaders avec la fonction "
+"[code]texture(SCREEN_TEXTURE, ...)[/code]."
#: doc/classes/BackBufferCopy.xml
msgid ""
@@ -13801,6 +13956,17 @@ msgid ""
"[b]Note:[/b] [member bounce_indirect_energy] only has an effect if [member "
"bounces] is set to a value greater than or equal to [code]1[/code]."
msgstr ""
+"Le multiplicateur d'énergie à chaque rebond. Des valeurs plus élevées "
+"rendront l'éclairage indirect plus lumineux. Une valeur de [code]1.0[/code] "
+"représente un comportement physiquement réaliste, mais des valeurs plus "
+"élevées peuvent être utilisées pour rendre l'éclairage indirect plus visible "
+"avec un faible nombre de rebonds. Cela peut être utilisé pour accélérer les "
+"temps de calcul des lumières en réduisant le nombre de [member bounces] puis "
+"en augmentant [member bounce_indirect_energy]. Contrairement à [member "
+"BakedLightmapData.energy], cette propriété n'affecte pas l'éclairage direct "
+"émis par les lumières, les matériaux avec émission et l'environnement.\n"
+"[b]Note :[/b] [member bounce_indirect_energy] a seulement un effet si "
+"[member bounces] est à une valeur supérieure ou égale à [code]1[/code]."
#: doc/classes/BakedLightmap.xml
msgid ""
@@ -13850,6 +14016,9 @@ msgid ""
"[constant ENVIRONMENT_MODE_CUSTOM_COLOR] or [constant "
"ENVIRONMENT_MODE_CUSTOM_SKY]."
msgstr ""
+"Le facteur d'énergie lorsque [member environment_mode] est défini à "
+"[constant ENVIRONMENT_MODE_CUSTOM_COLOR] ou [constant "
+"ENVIRONMENT_MODE_CUSTOM_SKY]."
#: doc/classes/BakedLightmap.xml
msgid ""
@@ -14027,17 +14196,25 @@ msgid ""
"directly (it doesn't display anything). Other types of buttons inherit from "
"it."
msgstr ""
+"BaseButton est la classe de base abstraite pour les boutons, elle ne doit "
+"donc pas être utilisée directement (elle ne montre rien du tout). D'autres "
+"types de boutons héritent de cette classe."
#: doc/classes/BaseButton.xml
msgid ""
"Called when the button is pressed. If you need to know the button's pressed "
"state (and [member toggle_mode] is active), use [method _toggled] instead."
msgstr ""
+"Appelé quand le bouton est pressé. Si vous avez besoin de connaître l'état "
+"du bouton activé (et que [member toggle_mode] est actif), utilisez plutôt "
+"[méthode _toggled]."
#: doc/classes/BaseButton.xml
msgid ""
"Called when the button is toggled (only if [member toggle_mode] is active)."
msgstr ""
+"Appelé quand un bouton est basculé (seulement si [member toggle_mode] est "
+"actif)."
#: doc/classes/BaseButton.xml
msgid ""
@@ -14046,6 +14223,10 @@ msgid ""
"to \"draw\" signal. The visual state of the button is defined by the [enum "
"DrawMode] enum."
msgstr ""
+"Retourne l'état visuel utilisé pour dessiner le bouton. Ceci est utile "
+"surtout pour implémenter votre propre code d'affichage en surchargeant "
+"_draw() ou en se connectant au signal \"draw\". L'état visuel du bouton est "
+"défini par l'enumération [enum DrawMode]."
#: doc/classes/BaseButton.xml
#, fuzzy
@@ -14065,6 +14246,13 @@ msgid ""
"[b]Note:[/b] This method doesn't unpress other buttons in its button [member "
"group]."
msgstr ""
+"Change l'état [member pressed] du bouton, sans émettre le signal [signal "
+"toggled]. Utilisez lorsque vous voulez simplement changer l'état du bouton "
+"sans envoyer l'événement quand il est manuellement pressé (par exemple au "
+"moment de l'initialisation de la scène). Fonctionne seulement si [member "
+"toggle_mode] est [code]true[/code].\n"
+"[b]Note :[/b] Cette méthode ne déselectionne pas les autres boutons dans son "
+"[member group]."
#: doc/classes/BaseButton.xml
msgid ""
@@ -14080,12 +14268,18 @@ msgid ""
"To allow both left-click and right-click, use [code]BUTTON_MASK_LEFT | "
"BUTTON_MASK_RIGHT[/code]."
msgstr ""
+"La masque binaire pour choisir quels boutons de clic de la souris permet "
+"d'appuyer sur ce bouton.\n"
+"Pour permettre à la fois le clic gauche et le clic droit, utilisez "
+"[code]BUTTON_MASK_LEFT | BUTTON_MASK_RIGHT[/code]."
#: doc/classes/BaseButton.xml
msgid ""
"If [code]true[/code], the button is in disabled state and can't be clicked "
"or toggled."
msgstr ""
+"Si [code]true[/code], le bouton est désactivé et il ne peut donc pas être "
+"appuyé ou basculé."
#: doc/classes/BaseButton.xml
msgid ""
@@ -14093,6 +14287,9 @@ msgid ""
"will be removed in Godot 4.0. This property no longer has any effect when "
"set. Please use [member Control.focus_mode] instead."
msgstr ""
+"[i]Obsolète.[/i] Cette propriété est obsolète en raison de sa redondance et "
+"sera enlevée dans Godot 4.0. Cette propriété n'a plus d'effet quand elle est "
+"définie. Veuillez plutôt utiliser [member Control.focus_mode]."
#: doc/classes/BaseButton.xml
msgid "[ButtonGroup] associated to the button."
@@ -14106,6 +14303,11 @@ msgid ""
"Signals will be emitted at the same moment regardless of this property's "
"value."
msgstr ""
+"Si [code]true[/code], le bouton reste pressé quand le clic est maintenu mais "
+"que le curseur est déplacé en dehors du bouton.\n"
+"[b]Note :[/b] Cette propriété n'affecte que l'aspect visuel du bouton. Les "
+"signaux seront toujours émis au même moment, peu importe la valeur de cette "
+"propriété."
#: doc/classes/BaseButton.xml
msgid ""
@@ -14116,6 +14318,12 @@ msgid ""
"emitted. If you want to change the pressed state without emitting that "
"signal, use [method set_pressed_no_signal]."
msgstr ""
+"Si [code]true[/code], l'état du bouton est appuyé. Ce qui signifie que le "
+"bouton est soit appuyé ou basculé (si [member toggle_mode] est actif). Ne "
+"fonctionne que si [member toggle_mode] est [code]true[/code].\n"
+"[b]Note :[/b] Activer [member pressed] émettra le signal [signal toggled]. "
+"Si vous voulez changer l'état pressé sans émettre ce signal, utilisez plutôt "
+"[method set_pressed_no_signal]."
#: doc/classes/BaseButton.xml
msgid "[ShortCut] associated to the button."
@@ -14164,6 +14372,8 @@ msgid ""
"The normal state (i.e. not pressed, not hovered, not toggled and enabled) of "
"buttons."
msgstr ""
+"L'état normal (c'est-à-dire non pressé, non survolé, non basculé ni activé) "
+"des boutons."
#: doc/classes/BaseButton.xml
msgid "The state of buttons are pressed."
@@ -14210,6 +14420,17 @@ msgid ""
"For more information, read the \"Matrices and transforms\" documentation "
"article."
msgstr ""
+"Une matrice 3×3 utilisée pour la rotation et la mise à l'échelle en 3D. "
+"Presque toujours utilisé comme base orthogonale pour une Transform.\n"
+"Contient 3 champs vectoriels X, Y et Z qui composent ses colonnes, qui sont "
+"généralement interprétées comme les vecteurs de base locaux d'une "
+"transformation. Pour une telle utilisation, c'est composé d'une mise à "
+"l'échelle et d'une matrice de rotation, dans cet ordre (M = R.S)\n"
+"Peut également être accessible comme un tableau de vecteurs 3D. Ces vecteurs "
+"sont normalement orthogonaux l'un avec l'autre, mais ne sont pas "
+"nécessairement normalisés (en raison de la mise à l'échelle).\n"
+"Pour plus d'informations, lisez l'article de documentation « Matrices et "
+"transformations »."
#: doc/classes/Basis.xml doc/classes/Transform.xml doc/classes/Transform2D.xml
msgid "Matrices and transforms"
@@ -14221,7 +14442,6 @@ msgstr "Utiliser les transformations 3D"
#: doc/classes/Basis.xml doc/classes/Line2D.xml doc/classes/Transform.xml
#: doc/classes/Transform2D.xml doc/classes/Vector2.xml doc/classes/Vector3.xml
-#, fuzzy
msgid "Matrix Transform Demo"
msgstr "Démo de transformation matricielle"
@@ -14256,16 +14476,21 @@ msgid ""
"Consider using the [Quat] constructor instead, which uses a quaternion "
"instead of Euler angles."
msgstr ""
+"Construit une matrice de base de rotation pure à partir des angles d'Euler "
+"spécifiés (suivant la convention YXZ : lors de la *composition*, d'abord Y, "
+"puis X, et enfin Z), qui sont donnés dans un vecteur comme (angle X, angle "
+"Y, angle Z).\n"
+"Vous pouvez considérer l'utilisation du constructeur [Quat], qui utilise un "
+"quaternion au lieu des angles d'Euler."
#: doc/classes/Basis.xml
-#, fuzzy
msgid ""
"Constructs a pure rotation basis matrix, rotated around the given "
"[code]axis[/code] by [code]angle[/code] (in radians). The axis must be a "
"normalized vector."
msgstr ""
-"Construit un quaternion qui tournera autour de l'axe donné selon l'angle "
-"spécifié. L'axe doit être un vecteur normalisé."
+"Construit un quaternion qui tournera autour de l'axe [code]axis[/code] par "
+"[code]angle[/code] (en radians). L'axe doit être un vecteur normalisé."
#: doc/classes/Basis.xml
msgid "Constructs a basis matrix from 3 axis vectors (matrix columns)."
@@ -14387,18 +14612,24 @@ msgid ""
"The basis matrix's X vector (column 0). Equivalent to array index [code]0[/"
"code]."
msgstr ""
+"Le vecteur X (la colonne 0) de la matrice de la base. Équivalent à l'index "
+"de tableau [code]0[/code]."
#: doc/classes/Basis.xml doc/classes/Transform2D.xml
msgid ""
"The basis matrix's Y vector (column 1). Equivalent to array index [code]1[/"
"code]."
msgstr ""
+"Le vecteur Y (la colonne 1) de la matrice de la base. Équivalent à l'index "
+"de tableau [code]1[/code]."
#: doc/classes/Basis.xml
msgid ""
"The basis matrix's Z vector (column 2). Equivalent to array index [code]2[/"
"code]."
msgstr ""
+"Le vecteur Z (la colonne 2) de la matrice de la base. Équivalent à l'index "
+"de tableau [code]2[/code]."
#: doc/classes/Basis.xml
msgid ""
@@ -14407,24 +14638,34 @@ msgid ""
"This constant can be used to make your code clearer, and for consistency "
"with C#."
msgstr ""
+"La base d'identité, sans rotation ni mise à l'échelle.\n"
+"Ceci est identique à [code]Basis()[/code] sans aucun paramètre. Cette "
+"constante peut être utilisée pour que votre code soit plus clair, et pour la "
+"cohérence avec C#."
#: doc/classes/Basis.xml
msgid ""
"The basis that will flip something along the X axis when used in a "
"transformation."
msgstr ""
+"La base qui appliquera un effet miroir suivant l'axe X lorsqu'elle est "
+"utilisée dans une transformation."
#: doc/classes/Basis.xml
msgid ""
"The basis that will flip something along the Y axis when used in a "
"transformation."
msgstr ""
+"La base qui appliquera un effet miroir suivant l'axe Y lorsqu'elle est "
+"utilisée dans une transformation."
#: doc/classes/Basis.xml
msgid ""
"The basis that will flip something along the Z axis when used in a "
"transformation."
msgstr ""
+"La base qui appliquera un effet miroir suivant l'axe Z lorsqu'elle est "
+"utilisée dans une transformation."
#: doc/classes/BitMap.xml
msgid "Boolean matrix."
@@ -14436,6 +14677,10 @@ msgid ""
"a binary matrix (every matrix element takes only one bit) and query the "
"values using natural cartesian coordinates."
msgstr ""
+"Un tableau bidimensionnel de valeurs booléennes, peut être utilisé pour "
+"stocker efficacement une matrice binaire (chaque élément matrice ne contient "
+"qu'un bit) et faire des requêtes sur ces valeurs à l'aide de coordonnées "
+"naturelles cartésiennes."
#: doc/classes/BitMap.xml
msgid ""
@@ -14444,6 +14689,10 @@ msgid ""
"are being converted into white pixels, and [code]false[/code] bits into "
"black."
msgstr ""
+"Retourne une image de la même taille que la bitmap au format [enum.Format] "
+"du type [code]FORMAT_L8[/code]. Les valeurs [code]true[/code] de l'image "
+"seront converties en pixels blancs, et les valeurs [code]false[/code] en "
+"noir."
#: doc/classes/BitMap.xml
msgid ""
@@ -14459,6 +14708,10 @@ msgid ""
"that position is equal to [code]threshold[/code] or less, and [code]true[/"
"code] in other case."
msgstr ""
+"Crée un bitmap qui correspond aux dimensions de l'image donnée, chaque "
+"élément du bitmap sera remplacé par [code]false[/code] si l'opacité de ce "
+"pixel est inférieur ou égal à [code]threshold[/code], et [code]true[/code] "
+"sinon."
#: doc/classes/BitMap.xml
msgid "Returns bitmap's value at the specified position."
@@ -14481,6 +14734,12 @@ msgid ""
"area where the morphological operation is applied. Pixels located outside "
"the [code]rect[/code] are unaffected by [method grow_mask]."
msgstr ""
+"Applique une dilatation ou une érosion morphologique du bitmap. Si "
+"[code]pixels[/code] est positif, une dilatation est appliquée au bitmap. Si "
+"[code]pixels[/code] est négatif, une érosion est appliquée. [code]rect[/"
+"code] définit la zone où l'opération morphologique est appliquée. Les pixels "
+"situés à l'extérieur du [code]rect[/code] ne sont pas affectés par [method "
+"grow_mask]."
#: doc/classes/BitMap.xml
msgid "Resizes the image to [code]new_size[/code]."
@@ -14607,6 +14866,9 @@ msgid ""
"Returns the node's [member rest] [code]Transform2D[/code] if it doesn't have "
"a parent, or its rest pose relative to its parent."
msgstr ""
+"Retourne la [code]Transform2D[/code] du nœud pour la position de repos "
+"[member rest] s'il n'a pas de parent, ou si sa position de repos est "
+"relative à son parent."
#: doc/classes/Bone2D.xml
msgid ""
@@ -14633,6 +14895,9 @@ msgid ""
"for this node to attach to. The BoneAttachment node will copy the transform "
"of the selected bone."
msgstr ""
+"Ce nœud doit être l'enfant d'un nœud [Skeleton]. Vous pouvez alors "
+"sélectionner un os pour que ce nœud soit attaché. Le nœud BoneAttachment "
+"copiera la transformation de l'os sélectionné."
#: doc/classes/BoneAttachment.xml
msgid "The name of the attached bone."
@@ -14767,6 +15032,11 @@ msgid ""
"Examples: [code]bool(\"False\")[/code] returns [code]true[/code], "
"[code]bool(\"\")[/code] returns [code]false[/code]."
msgstr ""
+"Convertit une valeur [String] en valeur booléenne, cette méthode retournera "
+"[code]false[/code] si [code]\"\"[/code] est donné, et [code]true[/code] pour "
+"toute chaîne non vide.\n"
+"Exemples : [code]bool(\"False\")[/code] retourne [code]true[/code], "
+"[code]bool(\"\")[/code] retourne [code]false[/code]."
#: doc/classes/BoxContainer.xml
msgid "Base class for box containers."
@@ -14777,12 +15047,16 @@ msgid ""
"Arranges child controls vertically or horizontally, and rearranges the "
"controls automatically when their minimum size changes."
msgstr ""
+"Arrange les contrôles enfants verticalement ou horizontalement, et "
+"réorganise les contrôles automatiquement lorsque leur taille minimale change."
#: doc/classes/BoxContainer.xml
msgid ""
"Adds a control to the box as a spacer. If [code]true[/code], [code]begin[/"
"code] will insert the spacer control in front of other children."
msgstr ""
+"Ajoute un contrôle à la boîte comme espace. Si [code]true[/code], "
+"[code]begin[/code] insérera le contrôle d'espace devant les autres enfants."
#: doc/classes/BoxContainer.xml
msgid ""
@@ -14819,20 +15093,22 @@ msgstr ""
#: doc/classes/RigidBody.xml doc/classes/SphereShape.xml
#: doc/classes/StaticBody.xml
msgid "3D Physics Tests Demo"
-msgstr ""
+msgstr "Démo des tests de physique 3D"
#: doc/classes/BoxShape.xml doc/classes/CollisionShape.xml
#: modules/gridmap/doc_classes/GridMap.xml doc/classes/KinematicBody.xml
#: doc/classes/Mesh.xml doc/classes/MeshInstance.xml
#: doc/classes/MeshLibrary.xml
msgid "3D Kinematic Character Demo"
-msgstr ""
+msgstr "Démo de caractère cinématique 3D"
#: doc/classes/BoxShape.xml
msgid ""
"The box's half extents. The width, height and depth of this shape is twice "
"the half extents."
msgstr ""
+"La demi-étendue de la boîte. La largeur, la hauteur et la profondeur de "
+"cette forme sont deux fois plus larges."
#: doc/classes/Button.xml
msgid "Standard themed Button."
@@ -14893,7 +15169,7 @@ msgstr ""
#: doc/classes/PoolStringArray.xml doc/classes/ProjectSettings.xml
#: doc/classes/ResourceLoader.xml doc/classes/RichTextLabel.xml
msgid "OS Test Demo"
-msgstr ""
+msgstr "Démo de test de système d'exploitation"
#: doc/classes/Button.xml
msgid ""
@@ -14909,12 +15185,17 @@ msgid ""
"clipped, when disabled the Button will always be wide enough to hold the "
"text."
msgstr ""
+"Lorsque cette propriété est activée, un texte trop grand pour ce bouton sera "
+"tronqué, et lorsque le bouton est désactivé, il sera toujours assez grand "
+"pour contenir tout le texte."
#: doc/classes/Button.xml
msgid ""
"When enabled, the button's icon will expand/shrink to fit the button's size "
"while keeping its aspect."
msgstr ""
+"Lorsque actif, l'icône du bouton s'étendra/se réduira selon la taille du "
+"bouton et gardera son aspect."
#: doc/classes/Button.xml
msgid "Flat buttons don't display decoration."
@@ -14927,6 +15208,11 @@ msgid ""
"property of [Button] and [code]content_margin_*[/code] properties of the "
"used [StyleBox]es."
msgstr ""
+"L'icône du bouton, si le texte est présent, l'icône sera placée avant le "
+"texte.\n"
+"Pour modifier la marge et l'espacement de l'icône, utilisez la propriété "
+"[code]hseparation[/code] du thème pour le [Button] et les propriétés "
+"[code]content_margin_*[/code] de la [StyleBox] utilisée."
#: doc/classes/Button.xml
msgid ""
@@ -14934,6 +15220,10 @@ msgid ""
"button. Uses the same [enum TextAlign] constants as the text alignment. If "
"centered, text will draw on top of the icon."
msgstr ""
+"Spécifie si l'icône doit être alignée sur la gauche, la droite ou au centre "
+"d'un bouton. Utilisez les mêmes constantes [enum TextAlign] que pour "
+"l'alignement du texte. Si l'icône est centrée, elle sera affichée sous le "
+"texte."
#: doc/classes/Button.xml doc/classes/LinkButton.xml
msgid "The button's text that will be displayed inside the button's area."
@@ -14965,6 +15255,9 @@ msgid ""
"text color of the button. Disabled, hovered, and pressed states take "
"precedence over this color."
msgstr ""
+"La [Color] du texte utilisée lorsque le [Button] a le focus. Ne fait que "
+"remplacer la couleur normale du texte du bouton. Les couleurs définies pour "
+"les états désactivé, survolé et pressé sont prioritaires sur cette couleur."
#: doc/classes/Button.xml
msgid "Text [Color] used when the [Button] is being hovered."
@@ -14992,6 +15285,9 @@ msgid ""
"current [StyleBox], so using [StyleBoxEmpty] will just disable the focus "
"visual effect."
msgstr ""
+"La [StyleBox] utilisée lorsque le [Button] a le focus. Elle est affichée par "
+"dessus la [StyleBox] actuelle, donc en utilisant [StyleBoxEmpty], ne fera "
+"que désactiver l'effet visuel quand le bouton a le focus."
#: doc/classes/Button.xml
msgid "[StyleBox] used when the [Button] is being hovered."
@@ -15015,6 +15311,10 @@ msgid ""
"Only one allows being pressed.\n"
"[member BaseButton.toggle_mode] should be [code]true[/code]."
msgstr ""
+"Un groupe de [Button]. Tous les boutons enfants directs et indirects "
+"deviennent des boutons radios. Un seul de ces boutons peut être pressé à la "
+"fois.\n"
+"[member BaseButton.toggle_mode] devrait être [code]true[/code]."
#: doc/classes/ButtonGroup.xml
msgid ""
@@ -15098,6 +15398,9 @@ msgid ""
"[code]enable_next[/code] is [code]true[/code], request to make the next "
"camera current, if any."
msgstr ""
+"Si c'est la caméra actuelle, elle ne sera plus l'actuelle. Si "
+"[code]enable_next[/code] est [code]true[/code], passe à la caméra suivante "
+"pour la rendre actuelle, s'il y en a une."
#: doc/classes/Camera.xml
msgid "Returns the camera's RID from the [VisualServer]."
@@ -15110,6 +15413,10 @@ msgid ""
"to the position and orientation of the camera by subclassed cameras such as "
"[ClippedCamera], [InterpolatedCamera] and [ARVRCamera]."
msgstr ""
+"Retourne la transformation de la caméra avec les décalages vertical ([member "
+"v_offset]) et horizontal ([member h_offset]) ; et tout autre ajustement "
+"apporté à la position et à l'orientation de la caméra par les sous-classes "
+"de caméra comme [ClippedCamera], [InterpolatedCamera] et [ARVRCamera]."
#: doc/classes/Camera.xml
msgid ""
@@ -15539,6 +15846,9 @@ msgid ""
"The custom [Viewport] node attached to the [Camera2D]. If [code]null[/code] "
"or not a [Viewport], uses the default viewport instead."
msgstr ""
+"Le nœud [Viewport] personnalisé attaché à la [Camera2D]. Si [code]null[/"
+"code] ou que ça n'est pas un [Viewport], ça utilise la fenêtre d'affichage "
+"par défaut à la place."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15627,6 +15937,13 @@ msgid ""
"without smoothing, even with this setting enabled, invoke [method "
"reset_smoothing]."
msgstr ""
+"Si [code]true[/code], la caméra s'arrête en douceur quand elle atteint ses "
+"limites.\n"
+"Cette propriété n'a aucun effet si [member smoothing_enabled] est "
+"[code]false[/code].\n"
+"[b]Note :[/b] Pour mettre immédiatement à jour la position de la caméra "
+"activée sans ralenti, même avec ce réglage activé, appelez [method "
+"reset_smoothing]."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15679,6 +15996,8 @@ msgid ""
"Speed in pixels per second of the camera's smoothing effect when [member "
"smoothing_enabled] is [code]true[/code]."
msgstr ""
+"La vitesse en pixels par seconde de l'effet de ralenti de la caméra quand "
+"[member smoothing_enabled] est [code]true[/code]."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15687,6 +16006,10 @@ msgid ""
"example, use [code]Vector2(0.5, 0.5)[/code] for a 2× zoom-in, and "
"[code]Vector2(4, 4)[/code] for a 4× zoom-out."
msgstr ""
+"Le zoom de l'appareil photo relatif à la fenêtre d'affichage. Les valeurs "
+"supérieures à [code]Vector2(1, 1)[/code] font un zoom arrière et les valeurs "
+"plus petites un zoom avant. Par exemple, utilisez [code]Vector2(0.5, 0.5)[/"
+"code] pour un zoom à 50%, et [code]Vector2(4, 4)[/code] pour un zoom 4×."
#: doc/classes/Camera2D.xml
msgid ""
@@ -15705,10 +16028,12 @@ msgstr ""
"et la taille de l'écran."
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr "La caméra se met à jour avec le rappel [code]_physics_process[/code]."
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr "La caméra se met à jour durant l'appel de [code]_process[/code]."
@@ -16082,6 +16407,8 @@ msgid ""
"Draws a [Mesh] in 2D, using the provided texture. See [MeshInstance2D] for "
"related documentation."
msgstr ""
+"Dessine un [Mesh] en 2D, en utilisant la texture spécifiée. Voir "
+"[MeshInstance2D] pour la documentation en rapport."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16143,6 +16470,8 @@ msgid ""
"Draws a [MultiMesh] in 2D with the provided texture. See "
"[MultiMeshInstance2D] for related documentation."
msgstr ""
+"Dessine un [MultiMesh] en 2D avec la texture spécifiée. Voir "
+"[MultiMeshInstance2D] pour la documentation en rapport."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16381,6 +16710,8 @@ msgid ""
"Returns the mouse's position in the [CanvasLayer] that this [CanvasItem] is "
"in using the coordinate system of the [CanvasLayer]."
msgstr ""
+"Retourne la position de la souris dans le [CanvasLayer] que ce [CanvasItem] "
+"utilise suivant le système de coordonnées du [CanvasLayer]."
#: doc/classes/CanvasItem.xml
msgid "Returns the global transform matrix of this item."
@@ -16398,6 +16729,8 @@ msgid ""
"Returns the mouse's position in this [CanvasItem] using the local coordinate "
"system of this [CanvasItem]."
msgstr ""
+"Retourne la position de la souris dans le [CanvasItem] en utilisant le "
+"système de coordonnées local au [CanvasItem]."
#: doc/classes/CanvasItem.xml
msgid "Returns the transform matrix of this item."
@@ -16422,6 +16755,8 @@ msgid ""
"Hide the [CanvasItem] if it's currently visible. This is equivalent to "
"setting [member visible] to [code]false[/code]."
msgstr ""
+"Cacher les [CanvasItem] s'ils sont actuellement visibles. C'est équivalent à "
+"[member visible] à [code]false[/code]."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16436,6 +16771,8 @@ msgid ""
"Returns [code]true[/code] if the node is set as top-level. See [method "
"set_as_toplevel]."
msgstr ""
+"Retourne [code]true[/code] si le nœud est défini comme de niveau supérieur. "
+"Voir [méthode set_as_toplevel]."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16452,16 +16789,24 @@ msgid ""
"also visible. If any antecedent is hidden, this node will not be visible in "
"the scene tree."
msgstr ""
+"Retourne [code]true[/code] si le nœud est présent dans le [SceneTree], que "
+"sa propriété [member visible] est [code]true[/code] et que tous ses parents "
+"sont également visibles. Si un parent est caché, ce nœud ne sera pas visible "
+"dans l'arborescence de la scène."
#: doc/classes/CanvasItem.xml
msgid "Assigns [code]screen_point[/code] as this node's new local transform."
msgstr ""
+"Assigne [code]screen_point[/code] comme la nouvelle position locale de ce "
+"nœud."
#: doc/classes/CanvasItem.xml
msgid ""
"Transformations issued by [code]event[/code]'s inputs are applied in local "
"space instead of global space."
msgstr ""
+"Les transformations émises par les entrées de [code]event[/code] sont "
+"appliquées dans l'espace local au lieu de l'espace global."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16503,12 +16848,18 @@ msgid ""
"[Popup], the correct way to make them visible is to call one of the multiple "
"[code]popup*()[/code] functions instead."
msgstr ""
+"Affiche le [CanvasItem] s'il est actuellement caché. Ceci est équivalent à "
+"[member visible] à [code]true[/code]. Pour les contrôles hérités de [Popup], "
+"appelez plutôt l'une des fonctions [code]popup*()[/code] pour le rendre "
+"visible."
#: doc/classes/CanvasItem.xml
msgid ""
"Queue the [CanvasItem] for update. [constant NOTIFICATION_DRAW] will be "
"called on idle time to request redraw."
msgstr ""
+"Ajoute le [CanvasItem] pour être mis à jour. [constant NOTIFICATION_DRAW] "
+"sera émise sur le temps inoccupé pour demander la mise à jour."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16543,6 +16894,8 @@ msgid ""
"If [code]true[/code], the parent [CanvasItem]'s [member material] property "
"is used as this one's material."
msgstr ""
+"Si [code]true[/code], la propriété [member material] du [CanvasItem] parent "
+"est utilisée comme matériau de celui-ci."
#: doc/classes/CanvasItem.xml
msgid ""
@@ -16553,12 +16906,21 @@ msgid ""
"visible is to call one of the multiple [code]popup*()[/code] functions "
"instead."
msgstr ""
+"Si [code]true[/code], ce [CanvasItem] est affiché. Le nœud n'est visible que "
+"si tous ses parents le sont également (en d'autres termes, [méthode "
+"is_visible_in_tree] doit retourner [code]true[/code]).\n"
+"[b]Note :[/b] Pour les contrôles qui héritent de [Popup], la bonne manière "
+"de les rendre visible est plutôt d'appeler l'une des fonctions [code]popup*()"
+"[/code]."
#: doc/classes/CanvasItem.xml
msgid ""
"Emitted when the [CanvasItem] must redraw. This can only be connected "
"realtime, as deferred will not allow drawing."
msgstr ""
+"Émis lorsque le [CanvasItem] doit être redessiné. Ça ne peut être que "
+"connecté qu'en temps réel, puisque le différer peut ne pas permettre le "
+"dessin."
#: doc/classes/CanvasItem.xml
msgid "Emitted when becoming hidden."
@@ -16570,6 +16932,9 @@ msgid ""
"or when an action is taking place that may have impacted these boundaries (e."
"g. changing [member Sprite.texture])."
msgstr ""
+"Émis quand la position ou la taille du [Rect2] a changé, ou lorsqu'une "
+"action a changé ces valeurs là (par exemple en changeant [member Sprite."
+"texture])"
#: doc/classes/CanvasItem.xml
msgid "Emitted when the visibility (hidden/visible) changes."
@@ -16708,6 +17073,7 @@ msgid ""
"Render the material using both light and non-light sensitive material "
"properties."
msgstr ""
+"Fait le rendu du matériau avec et sans lumière des propriétés matérielles."
#: doc/classes/CanvasItemMaterial.xml
msgid "Render the material as if there were no light."
@@ -16751,18 +17117,24 @@ msgid ""
"Hides any [CanvasItem] under this [CanvasLayer]. This is equivalent to "
"setting [member visible] to [code]false[/code]."
msgstr ""
+"Masque tous les [CanvasItem] dans ce [CanvasLayer]. Ceci est équivalent à "
+"définir [member visible] à [code]false[/code]."
#: doc/classes/CanvasLayer.xml
msgid ""
"Shows any [CanvasItem] under this [CanvasLayer]. This is equivalent to "
"setting [member visible] to [code]true[/code]."
msgstr ""
+"Affiche tous les [CanvasItem] dans ce [CanvasLayer]. Ceci est équivalent à "
+"définir [member visible] à [code]true[/code]."
#: doc/classes/CanvasLayer.xml
msgid ""
"The custom [Viewport] node assigned to the [CanvasLayer]. If [code]null[/"
"code], uses the default viewport instead."
msgstr ""
+"Le nœud [Viewport] personnalisé assigné au [CanvasLayer]. Si [code]null[/"
+"code], ça utilise la fenêtre d'affichage par défaut à la place."
#: doc/classes/CanvasLayer.xml
msgid ""
@@ -16776,6 +17148,10 @@ msgid ""
"into the foreground should have increasing scales, while layers moving into "
"the background should have decreasing scales."
msgstr ""
+"Change la mise à l'échelle du calque en utilisant [member "
+"follow_viewport_enable]. Les calques se déplaçant au premier plan devraient "
+"avoir des mises à l'échelle croissantes, tandis que les calques se déplaçant "
+"dans le fond devraient avoir des mises à l'échelle décroissantes."
#: doc/classes/CanvasLayer.xml
msgid "Layer index for draw order. Lower values are drawn first."
@@ -16810,6 +17186,10 @@ msgid ""
"Unlike [member CanvasItem.visible], visibility of a [CanvasLayer] isn't "
"propagated to underlying layers."
msgstr ""
+"Si [code]false[/code], tous les [CanvasItem] dans ce [CanvasLayer] sont "
+"cachés.\n"
+"Contrairement à [member CanvasItem.visible], la visibilité d'un "
+"[CanvasLayer] n'est pas propagée aux calques enfants."
#: doc/classes/CanvasLayer.xml
#, fuzzy
@@ -16842,6 +17222,10 @@ msgid ""
"[b]Note:[/b] The capsule's total height is equal to [member mid_height] + 2 "
"* [member radius]."
msgstr ""
+"La hauteur de la partie du cylindrique au milieu de la capsule (donc sans "
+"les bouts hémisphériques).\n"
+"[b]Note :[/b] La hauteur totale de la capsule est égale à [member "
+"mid_height] + 2 * [member radius]."
#: doc/classes/CapsuleMesh.xml
msgid "Number of radial segments on the capsule mesh."
@@ -16880,12 +17264,16 @@ msgid ""
"CenterContainer keeps children controls centered. This container keeps all "
"children to their minimum size, in the center."
msgstr ""
+"CenterContainer garde centrés les contrôles enfants. Ce conteneur garde tous "
+"les enfants à leur taille minimale, dans son centre."
#: doc/classes/CenterContainer.xml
msgid ""
"If [code]true[/code], centers children relative to the [CenterContainer]'s "
"top left corner."
msgstr ""
+"Si [code]true[/code], centre les enfants par rapport au coin supérieur "
+"gauche du [CenterContainer])."
#: doc/classes/CharFXTransform.xml
msgid ""
@@ -17190,6 +17578,9 @@ msgid ""
"normal text color of the button. Disabled, hovered, and pressed states take "
"precedence over this color."
msgstr ""
+"La couleur du texte du [CheckButton] quand il a le focus. Ne remplace que la "
+"couleur de texte normale du bouton. Les états désactivés, survolé et pressés "
+"sont prioritaire sur cette couleur."
#: doc/classes/CheckButton.xml
msgid "The [CheckButton] text's font color when it's hovered."
@@ -17209,10 +17600,12 @@ msgstr "La couleur de la police du texte du [CheckButton] quand il est appuyé."
#: doc/classes/CheckButton.xml
msgid "The vertical offset used when rendering the toggle icons (in pixels)."
msgstr ""
+"Le décalage vertical utilisé lors du rendu des icônes de basculement (en "
+"pixels)."
#: doc/classes/CheckButton.xml
msgid "The separation between the toggle icon and the text (in pixels)."
-msgstr ""
+msgstr "La séparation entre l'icône de basculement et le texte (en pixels)."
#: doc/classes/CheckButton.xml
msgid "The [Font] to use for the [CheckButton] text."
@@ -17258,6 +17651,8 @@ msgid ""
"The [StyleBox] to display as a background when the [CheckButton] is hovered "
"and pressed."
msgstr ""
+"La [StyleBox] à afficher en fond lorsque le [CheckButton] est survolé et "
+"appuyé."
#: doc/classes/CheckButton.xml
msgid ""
@@ -17276,6 +17671,9 @@ msgid ""
"small characters and its collision detection with everything else is very "
"fast."
msgstr ""
+"Forme circulaire pour les collisions 2D. Cette forme est utile pour "
+"modéliser les boules ou les petits caractères et sa détection des collisions "
+"avec les autres éléments est très rapide."
#: doc/classes/CircleShape2D.xml
msgid "The circle's radius."
@@ -17295,6 +17693,8 @@ msgid ""
"Returns [code]true[/code] if you can instance objects from the specified "
"[code]class[/code], [code]false[/code] in other case."
msgstr ""
+"Retourne [code]true[/code] si vous pouvez instancer des objets à partir de "
+"[code]class[/code], [code]false[/code] dans un autre cas."
#: doc/classes/ClassDB.xml
msgid "Returns whether the specified [code]class[/code] is available or not."
@@ -17305,12 +17705,17 @@ msgid ""
"Returns a category associated with the class for use in documentation and "
"the Asset Library. Debug mode required."
msgstr ""
+"Retourne une catégorie associée à la classe à utiliser dans la documentation "
+"et la bibliothèque de ressources. Le mode débogage est nécessaire pour "
+"récupérer cette information."
#: doc/classes/ClassDB.xml
msgid ""
"Returns an array with all the keys in [code]enum[/code] of [code]class[/"
"code] or its ancestry."
msgstr ""
+"Retourne un tableau avec toutes les clés dans l'énumeration [code]enum[/"
+"code] de la [code]class[/code] ou de ses parents."
#: doc/classes/ClassDB.xml
#, fuzzy
@@ -17335,6 +17740,8 @@ msgid ""
"Returns an array with the names all the integer constants of [code]class[/"
"code] or its ancestry."
msgstr ""
+"Retourne un tableau avec le nom de toutes les constantes entières de "
+"[code]class[/code] ou de son parent."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17347,6 +17754,15 @@ msgid ""
"[b]Note:[/b] In exported release builds the debug info is not available, so "
"the returned dictionaries will contain only method names."
msgstr ""
+"Retourne un tableau avec toutes les méthodes de [code]class[/code] ou son "
+"parent si [code]no_inheritance[/code] est [code]false[/code]. Chaque élément "
+"du tableau est un [Dictionary] avec les clés suivantes : [code]args[/code], "
+"[code]default_args[/code], [code]flags[/code], [code]id[/code], [code]name[/"
+"code] et [code]return: (class_name, hint, hint_string, name, type, usage)[/"
+"code].\n"
+"[b]Note :[/b] Dans la version exportée, les informations de débogage ne sont "
+"pas disponibles, les dictionnaires retournés ne contiendront donc que le nom "
+"des méthodes."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17361,6 +17777,8 @@ msgid ""
"Returns an array with all the properties of [code]class[/code] or its "
"ancestry if [code]no_inheritance[/code] is [code]false[/code]."
msgstr ""
+"Retourne un tableau avec toutes les propriétés de [code]class[/code] ou de "
+"son parent si [code]no_inheritance[/code] est [code]false[/code]."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17370,6 +17788,11 @@ msgid ""
"[code]name[/code], [code]return: (class_name, hint, hint_string, name, type, "
"usage)[/code]."
msgstr ""
+"Retourne les données [code]signal[/code] de [code]class[/code] ou de son "
+"parent. La valeur retournée est un [Dictionary] avec les clés suivantes : "
+"[code]args[/code], [code]default_args[/code], [code]flags[/code], [code]id[/"
+"code], [code]name[/code] et [code]return: (class_name, hint, hint_string, "
+"name, type, usage)[/code]."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17377,6 +17800,9 @@ msgid ""
"if [code]no_inheritance[/code] is [code]false[/code]. Every element of the "
"array is a [Dictionary] as described in [method class_get_signal]."
msgstr ""
+"Retourne un tableau avec tous les signaux de [code]class[/code] ou son "
+"parent si [code]no_inheritance[/code] est [code]false[/code]. Chaque élément "
+"du tableau est un [Dictionary] comme détaillé dans [method class_get_signal]."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17391,6 +17817,8 @@ msgid ""
"Returns whether [code]class[/code] or its ancestry has an integer constant "
"called [code]name[/code] or not."
msgstr ""
+"Retourne si [code]class[/code] ou son parent a une constante entière appelée "
+"[code]name[/code] ou non."
#: doc/classes/ClassDB.xml
msgid ""
@@ -17483,6 +17911,8 @@ msgid ""
"Returns [code]true[/code] if the specified bit index is on.\n"
"[b]Note:[/b] Bit indices range from 0-19."
msgstr ""
+"Retourne [code]true[/code] si l'index de bit spécifié est actif.\n"
+"[b]Note :[/b] Les indices de bit vont de 0 à 19."
#: doc/classes/ClippedCamera.xml
msgid "Removes a collision exception with the specified node."
@@ -17497,6 +17927,8 @@ msgid ""
"Sets the specified bit index to the [code]value[/code].\n"
"[b]Note:[/b] Bit indices range from 0-19."
msgstr ""
+"Définit l'index de bit spécifié à [code]valeur[/code].\n"
+"[b]Note :[/b] Les indices des bit vont de 0 à 19."
#: doc/classes/ClippedCamera.xml
msgid "If [code]true[/code], the camera stops on contact with [Area]s."
@@ -17516,6 +17948,11 @@ msgid ""
"physics_introduction.html#collision-layers-and-masks]Collision layers and "
"masks[/url] in the documentation for more information."
msgstr ""
+"Le masque de collision de la caméra. Seuls les objets dans au moins une "
+"calque de collision correspondant au masque seront détectés. Voir "
+"[url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-"
+"and-masks]Calques et masques de collision[/url] dans la documentation pour "
+"plus d'informations."
#: doc/classes/ClippedCamera.xml
msgid ""
@@ -17541,6 +17978,13 @@ msgid ""
"owners are not nodes and do not appear in the editor, but are accessible "
"through code using the [code]shape_owner_*[/code] methods."
msgstr ""
+"CollisionObject est la classe de base pour les objets physiques. Il peut "
+"contenir n'importe quel nombre de formes [Shape] de collision. Chaque forme "
+"doit être assignée à un [i]propriétaire de forme[ /i]. Le CollisionObject "
+"peut avoir n'importe quel nombre de propriétaires de forme. Les "
+"propriétaires de forme ne sont pas des nœuds et ne apparaissent pas dans "
+"l'éditeur, mais sont accessibles par le code en utilisant les méthodes "
+"[code]shape_owner_*[/code]."
#: doc/classes/CollisionObject.xml
msgid ""
@@ -17550,6 +17994,11 @@ msgid ""
"surface at that point. Connect to the [signal input_event] signal to easily "
"pick up these events."
msgstr ""
+"Reçoie les [InputEvent] non traités. [code]position[/code] est la position "
+"dans l'espace global du curseur de la souris sur la surface de la forme avec "
+"index [code]shape_idx[/code] et [code]normal[/code] est le vecteur de "
+"normale de la surface à ce point. Connectez-vous au signal [signal "
+"input_event] pour récupérer facilement ces événements."
#: doc/classes/CollisionObject.xml doc/classes/CollisionObject2D.xml
msgid ""
@@ -18001,6 +18450,13 @@ msgid ""
"only helper to create shapes, use [method CollisionObject."
"shape_owner_get_shape] to get the actual shape."
msgstr ""
+"Un élément d'aide de l'éditeur pour créer et modifier des formes de "
+"collision dans l'espace 3D. Vous pouvez utiliser ce nœud pour représenter "
+"toutes sortes de formes de collision, par exemple, ajoutez-le à un [Area] "
+"pour lui donner une forme de détection, ou l'ajoutez-le à un [PhysicsBody] "
+"pour créer un objet solide. [b]IMPORTANT[/b] : c'est une aide de l'éditeur "
+"qui ne sert qu'à créer des formes, utiliser [method CollisionObject."
+"shape_owner_get_shape] pour obtenir la forme réelle."
#: doc/classes/CollisionShape.xml doc/classes/CollisionShape2D.xml
#: doc/classes/Physics2DDirectBodyState.xml
@@ -18048,6 +18504,13 @@ msgid ""
"Editor-only helper to create shapes, use [method CollisionObject2D."
"shape_owner_get_shape] to get the actual shape."
msgstr ""
+"Un élément d'aide de l'éditeur pour créer et modifier des formes de "
+"collision dans l'espace 2D. Vous pouvez utiliser ce nœud pour représenter "
+"toutes sortes de formes de collision, par exemple, ajoutez-le à un [Area] "
+"pour lui donner une forme de détection, ou l'ajoutez-le à un [PhysicsBody] "
+"pour créer un objet solide. [b]IMPORTANT[/b] : c'est une aide de l'éditeur "
+"qui ne sert qu'à créer des formes, utiliser [method CollisionObject."
+"shape_owner_get_shape] pour obtenir la forme réelle."
#: doc/classes/CollisionShape2D.xml doc/classes/KinematicBody2D.xml
#: doc/classes/RectangleShape2D.xml doc/classes/TileMap.xml
@@ -18245,6 +18708,12 @@ msgid ""
"var darkgreen = green.darkened(0.2) # 20% darker than regular green\n"
"[/codeblock]"
msgstr ""
+"Retourne une nouvelle couleur à partir de cette couleur en plus foncée par "
+"le pourcentage donné (de 0 à 1).\n"
+"[codeblock]\n"
+"var green = Couleur(0.0, 1.0, 0.0) # Vert vif\n"
+"var darkgreen = vert.darkened(0.2) # 20% plus foncé que le vert vif\n"
+"/[codeblock]"
#: doc/classes/Color.xml
msgid ""
@@ -18268,6 +18737,11 @@ msgid ""
"This is useful when determining light or dark color. Colors with a luminance "
"smaller than 0.5 can be generally considered dark."
msgstr ""
+"Retourne la luminosité de la couleur dans l'intervalle [code][0.0, 1.0][/"
+"code].\n"
+"Ceci est utile pour déterminer si c'est une couleur claire ou foncée. Les "
+"couleurs avec une luminosité inférieure à 0,5 peuvent généralement être "
+"considérées comme sombres."
#: doc/classes/Color.xml
msgid ""
@@ -18428,7 +18902,7 @@ msgid ""
"[/codeblock]"
msgstr ""
"Retourne la chaîne de caractères avec le code hexadécimal façon HTML au "
-"format ARGB (par exemple [code]ff34f822[/code)].\n"
+"format ARGB (par exemple [code]ff34f822[/code]).\n"
"Définir [code]with_alpha[/code] à [code]false[/code] ne retourne pas la "
"valeur alpha dans le code hexadécimal retourné.\n"
"[codeblock]\n"
@@ -18862,7 +19336,7 @@ msgstr "Couleur marron."
#: doc/classes/Color.xml
#, fuzzy
msgid "Medium aquamarine color."
-msgstr "Couleur bleu-marin moyenne."
+msgstr "Couleur bleu-marine moyenne."
#: doc/classes/Color.xml
msgid "Medium blue color."
@@ -19089,22 +19563,18 @@ msgid "Violet color."
msgstr "Couleur violette."
#: doc/classes/Color.xml
-#, fuzzy
msgid "Web gray color."
msgstr "Couleur gris Web."
#: doc/classes/Color.xml
-#, fuzzy
msgid "Web green color."
-msgstr "Couleur verte web."
+msgstr "Couleur vert Web."
#: doc/classes/Color.xml
-#, fuzzy
msgid "Web maroon color."
msgstr "Couleur marron Web."
#: doc/classes/Color.xml
-#, fuzzy
msgid "Web purple color."
msgstr "Couleur violet Web."
@@ -19271,6 +19741,13 @@ msgid ""
"preview swatch to be visible. Make sure to set [member Control."
"rect_min_size] to a big enough value to give the button enough space."
msgstr ""
+"Encapsule un [ColorPicker] le rendant accessible en appuyant sur un bouton. "
+"En appuyant sur le bouton, le [ColorPicker] deviendra visible.\n"
+"Voir aussi [BaseButton] qui contient des propriétés et des méthodes communes "
+"associées à ce nœud.\n"
+"[b]Note :[/b] Par défaut, le bouton peut ne pas être assez large pour que "
+"les palettes de couleur soit visibles. Assurez-vous de configurer [member "
+"Control.rect_min_size] avec une taille suffisante grande pour le bouton."
#: doc/classes/ColorPickerButton.xml
msgid ""
@@ -19279,6 +19756,10 @@ msgid ""
"may cause a crash. If you wish to hide it or any of its children, use their "
"[member CanvasItem.visible] property."
msgstr ""
+"Retourne le [ColorPicker] que ce nœud bascule.\n"
+"[b]Avertissement :[/b] Il s'agit d'un nœud interne requis, le retirer et le "
+"supprimer peut causer un plantage. Si vous voulez le cacher ou l'un de ses "
+"enfants, utilisez la propriété [member CanvasItem.visible]."
#: doc/classes/ColorPickerButton.xml
msgid ""
@@ -19289,6 +19770,12 @@ msgid ""
"may cause a crash. If you wish to hide it or any of its children, use their "
"[member CanvasItem.visible] property."
msgstr ""
+"Retourne la commande suivante [PopupPanel] qui vous permet de vous connecter "
+"aux signaux de la fenêtre surgissante. Cela vous permet de gérer les "
+"événements lorsque le ColorPicker est affiché ou caché.\n"
+"[b]Avertissement :[/b] Il s'agit d'un nœud interne requis, le retirer et le "
+"supprimer peut causer un plantage. Si vous voulez le cacher ou l'un de ses "
+"enfants, utilisez la propriété [member CanvasItem.visible]."
#: doc/classes/ColorPickerButton.xml
msgid ""
@@ -19306,6 +19793,8 @@ msgid ""
"Emitted when the [ColorPicker] is created (the button is pressed for the "
"first time)."
msgstr ""
+"Émis lorsque le [ColorPicker] est créé (le bouton est pressé pour la "
+"première fois)."
#: doc/classes/ColorPickerButton.xml
msgid "Emitted when the [ColorPicker] is closed."
@@ -19326,6 +19815,9 @@ msgid ""
"normal text color of the button. Disabled, hovered, and pressed states take "
"precedence over this color."
msgstr ""
+"La [Color] du texte utilisée lorsque le [ColorPickerButton] a le focus. Il "
+"suffit de remplacer la couleur de texte normale du bouton. Les états "
+"désactivé, survolé et pressé sont prioritaires par rapport à cette couleur."
#: doc/classes/ColorPickerButton.xml
msgid "Text [Color] used when the [ColorPickerButton] is being hovered."
@@ -19358,6 +19850,9 @@ msgid ""
"over the current [StyleBox], so using [StyleBoxEmpty] will just disable the "
"focus visual effect."
msgstr ""
+"La [StyleBox] utilisée lorsque le [ColorPickerButton] a le focus. Il est "
+"affiché par dessus la [StyleBox] actuelle, donc utiliser [StyleBoxEmpty] ne "
+"fera que désactiver l'effet visuel de focus."
#: doc/classes/ColorPickerButton.xml
msgid "[StyleBox] used when the [ColorPickerButton] is being hovered."
@@ -19380,6 +19875,8 @@ msgid ""
"Displays a rectangle filled with a solid [member color]. If you need to "
"display the border alone, consider using [ReferenceRect] instead."
msgstr ""
+"Affiche un rectangle rempli de la couleur [member color]. Si vous devez "
+"seulement afficher la bordure, utilisez plutôt un [ReferenceRect]."
#: doc/classes/ColorRect.xml
msgid ""
@@ -19406,6 +19903,13 @@ msgid ""
"work with static [PhysicsBody] nodes like [StaticBody] and will not work "
"with [KinematicBody] or [RigidBody] with a mode other than Static."
msgstr ""
+"Une ressource en forme de polygone concave, qui peut être utilisée dans un "
+"[PhysicsBody] ou une aire. Cette forme est créée à partir d'une liste de "
+"triangles.\n"
+"[b]Note :[/b] Lorsque qu'elle est utilisée pour les collisions, "
+"[ConcavePolygonShape] ne fonctionnera qu'avec les nœuds statiques "
+"[PhysicsBody] comme les [StaticBody] et non pas avec [KinematicBody] ou "
+"[RigidBody] quand ils ne sont pas en mode Static."
#: doc/classes/ConcavePolygonShape.xml
msgid "Returns the faces (an array of triangles)."
@@ -19432,6 +19936,18 @@ msgid ""
"uses a more complex method of collision detection, and a convex one forces "
"itself to be convex in order to speed up collision detection."
msgstr ""
+"Une ressource en forme de polygone concave pour la physique 2D. Elle est "
+"composée de segments et est optimal pour les collisions complexes de "
+"concaves polygonales. Cependant, il n'est pas conseillé de l'utiliser pour "
+"les nœuds [RigidBody2D]. Un CollisionPolygon2D décomposé en convexes "
+"(solides) ou plusieurs objets convexes sont conseillés dans ce cas. Sinon, "
+"une forme en polygone concave 2D est préférable pour les collisions "
+"statiques.\n"
+"La principale différence entre un [ConvexPolygonShape2D] et un "
+"[ConcavePolygonShape2D] est qu'un polygone concave suppose qu'il contient "
+"des zones creusées à l'intérieur et doit utiliser une méthode plus complexe "
+"pour détecter les collisions, alors qu'un polygone convexe n'admet aucune "
+"zone creusée pour pouvoir accélérer la détection des collisions."
#: doc/classes/ConcavePolygonShape2D.xml
msgid ""
@@ -19702,6 +20218,11 @@ msgid ""
"loaded in the [ConfigFile] object which the method was called on.\n"
"Returns one of the [enum Error] code constants ([code]OK[/code] on success)."
msgstr ""
+"Charge le fichier de configuration crypté spécifié comme paramètre, en "
+"utilisant le mode de passe [code]password[/code] donné pour le décrypter. Le "
+"contenu du fichier est interprété puis chargé dans l'objet [ConfigFile] sur "
+"lequel la méthode a été appelée.\n"
+"Retourne un des codes [enum Error] ([code]OK[/code] si c'est un succès)."
#: doc/classes/ConfigFile.xml
msgid ""
@@ -19709,6 +20230,10 @@ msgid ""
"parsed and loaded in the ConfigFile object which the method was called on.\n"
"Returns one of the [enum Error] code constants ([code]OK[/code] on success)."
msgstr ""
+"Interprète la chaîne passée comme étant le contenu d'un fichier de "
+"configuration. La chaîne est interprétée puis chargée dans l'objet "
+"ConfigFile sur lequel la méthode a été appelée.\n"
+"Retourne un des codes [enum Error] ([code]OK[/code] si c'est un succès)."
#: doc/classes/ConfigFile.xml
msgid ""
@@ -19716,6 +20241,9 @@ msgid ""
"parameter. The output file uses an INI-style structure.\n"
"Returns one of the [enum Error] code constants ([code]OK[/code] on success)."
msgstr ""
+"Enregistre le contenu de l'objet [ConfigFile] au fichier spécifié en "
+"paramètre. Le fichier de sortie utilise une structure de type INI.\n"
+"Retourne un des codes [enum Error] ([code]OK[/code] si c'est un succès)."
#: doc/classes/ConfigFile.xml
msgid ""
@@ -20413,6 +20941,10 @@ msgid ""
"[member focus_neighbour_left], [member focus_neighbour_right] and [member "
"focus_neighbour_top]."
msgstr ""
+"Retourne le voisin de focus identifié par la constante [code]margin[/code] "
+"de l'énumération [enum Margin]. Une méthode de getter pour [member "
+"focus_neighbour_bottom], [member focus_neighbour_left], [member "
+"focus_neighbour_right] et [member focus_neighbour_top]."
#: doc/classes/Control.xml
msgid ""
@@ -20427,12 +20959,18 @@ msgid ""
"code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne une [Font] du premier [Theme] correspondant dans l'arborescence si "
+"ce [Theme] a une propriété de police nommée [code]name[/code] et du type de "
+"thème [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
"Returns the position and size of the control relative to the top-left corner "
"of the screen. See [member rect_position] and [member rect_size]."
msgstr ""
+"Retourne la position et la taille du contrôle par rapport au coin supérieur "
+"gauche de l'écran. Voir [member rect_position] et [member rect_size]."
#: doc/classes/Control.xml
msgid ""
@@ -20441,6 +20979,10 @@ msgid ""
"code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne une icône du premier [Theme] correspondant dans l'arborescence si "
+"ce [Theme] a une propriété d'icône nommée [code]name[/code] et du type de "
+"thème [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20448,6 +20990,10 @@ msgid ""
"Margin] enum. A getter method for [member margin_bottom], [member "
"margin_left], [member margin_right] and [member margin_top]."
msgstr ""
+"Retourne l'ancre identifiée par la constante [code]margin[/code] de "
+"l'énumeration [enum Margin]. Une méthode de getter pour [member "
+"margin_bottom], [member margin_left], [member margin_right] et [member "
+"margin_top]."
#: doc/classes/Control.xml
msgid "Returns the minimum size for this control. See [member rect_min_size]."
@@ -20468,6 +21014,8 @@ msgid ""
"Returns the position and size of the control relative to the top-left corner "
"of the parent Control. See [member rect_position] and [member rect_size]."
msgstr ""
+"Retourne la position et la taille du contrôle par rapport au coin supérieur "
+"gauche du contrôle parent. Voir [member rect_position] et [member rect_size]."
#: doc/classes/Control.xml
msgid "Returns the rotation (in radians)."
@@ -20480,6 +21028,10 @@ msgid ""
"[code]theme_type[/code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne une [StyleBox] du premier [Theme] correspondant dans l'arborescence "
+"si ce [Theme] a une propriété de boîte de style nommée [code]name[/code] et "
+"du type de thème [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20506,6 +21058,13 @@ msgid ""
"be clicked instead\n"
"[/codeblock]"
msgstr ""
+"Crée un [InputEventMouseButton] qui tente de cliquer sur le contrôle. Si "
+"l'événement est bien reçu, le contrôle prend le focus.\n"
+"[codeblock]\n"
+"func _process(delta:)\n"
+" grab_click_focus() # Lorsque vous cliquez sur un autre contrôle, ce nœud "
+"sera cliqué à la place\n"
+"/[codeblock]"
#: doc/classes/Control.xml
msgid ""
@@ -20522,6 +21081,10 @@ msgid ""
"code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne [code]true[/code] s'il y a un [Theme] correspondant dans "
+"l'arborescence qui a une propriété de couleur nommé [code]name[/code] et du "
+"type de thème [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20540,6 +21103,10 @@ msgid ""
"[code]theme_type[/code].\n"
"See [method get_color] for details."
msgstr ""
+"Retourne [code]true[/code] s'il y a un [Theme] correspondant dans "
+"l'arborescence qui a une propriété de constante nommée [/code]name[/code] et "
+"du type de thème [code]theme_type[/code].\n"
+"Voir [method get_color] pour plus de détails."
#: doc/classes/Control.xml
msgid ""
@@ -20612,6 +21179,12 @@ msgid ""
"[b]Note:[/b] If you want to check if a point is inside the control, you can "
"use [code]get_rect().has_point(point)[/code]."
msgstr ""
+"Une méthode virtuelle à implémenter par l'utilisateur. Retourne si le "
+"[code]point[/code] donné est à l'intérieur de ce contrôle.\n"
+"Si ce n'est pas le cas, le comportement par défaut vérifie si le point se "
+"trouve dans le rectant englobant du contrôle.\n"
+"[b]Note :[/b] Si vous voulez vérifier si un point est à l'intérieur du "
+"contrôle, vous pouvez utiliser [code]get_rect().has_point(point[/code]."
#: doc/classes/Control.xml
msgid ""
@@ -20746,6 +21319,11 @@ msgid ""
"If [code]keep_margins[/code] is [code]true[/code], control's position will "
"also be updated."
msgstr ""
+"Définit les ancres avec le préréglage [code]preset[/code] de l'énumeration "
+"[enum Control.LayoutPreset]. C'est le code équivalent à l'utilisation du "
+"menu \"Mise en page\" dans l'éditeur 2D.\n"
+"Si [code]keep_margins[/code] est [code]true[/code], la position du contrôle "
+"sera également mise à jour."
#: doc/classes/Control.xml
msgid ""
@@ -20883,6 +21461,10 @@ msgid ""
"margin_bottom], [member margin_left], [member margin_right] and [member "
"margin_top]."
msgstr ""
+"Régle la marge identifiée par la constante [code]margin[/code] de "
+"l'énumeration [enum Margin] à [code]offset[/code]. Une méthode de setter "
+"pour [member margin_bottom], [member margin_left], [member margin_right] et "
+"[member margin_top]."
#: doc/classes/Control.xml
msgid ""
@@ -20896,6 +21478,16 @@ msgid ""
"Use parameter [code]margin[/code] to determine the gap between the [Control] "
"and the edges."
msgstr ""
+"Définit les marges avec le préréglage [code]preset[/code] de l'énumeration "
+"[enum Control.LayoutPreset]. C'est le code équivalent à l'utilisation du "
+"menu Layout dans l'éditeur 2D.\n"
+"Utilisez le paramètre [code]resize_mode[/code] avec des constantes de [enum "
+"Control.LayoutPresetMode] pour mieux déterminer la taille résultante du "
+"[Control]. La taille constante sera ignorée si elle est utilisée avec des "
+"préréglages qui changent la taille, par exemple [code]PRESET_LEFT_WIDE[/"
+"code].\n"
+"Utiliser le paramètre [code]margin[/code] pour déterminer l'écart entre le "
+"[Contrôle] et les bords."
#: doc/classes/Control.xml
msgid ""
@@ -20903,6 +21495,9 @@ msgid ""
"If [code]keep_margins[/code] is [code]true[/code], control's anchors will be "
"updated instead of margins."
msgstr ""
+"Défini le [member rect_position] à la [code]position[/code] spécifiée.\n"
+"Si [code]keep_margins[/code] est [code]true[/code], les ancres du contrôle "
+"sont mis à jour au lieu des marges."
#: doc/classes/Control.xml
msgid "Sets the rotation (in radians)."
@@ -20914,6 +21509,9 @@ msgid ""
"If [code]keep_margins[/code] is [code]true[/code], control's anchors will be "
"updated instead of margins."
msgstr ""
+"Définit la taille (voir [member rect_size]).\n"
+"Si [code]keep_margins[/code] est [code]true[/code], les ancres du contrôle "
+"sont mis à jour au lieu des marges."
#: doc/classes/Control.xml
msgid ""
@@ -20941,6 +21539,10 @@ msgid ""
"moves or changes size. You can use one of the [enum Anchor] constants for "
"convenience."
msgstr ""
+"L'ancre du bord du bas du nœud par rapport à l'origine, le centre, ou la fin "
+"de son contrôle parent. Il modifie la mise à jour de la marge inférieure "
+"lorsque le nœud se déplace ou change la taille. Vous pouvez utiliser une des "
+"constantes de [enum Anchor] suivant les besoins."
#: doc/classes/Control.xml
msgid ""
@@ -20949,6 +21551,10 @@ msgid ""
"moves or changes size. You can use one of the [enum Anchor] constants for "
"convenience."
msgstr ""
+"L'ancre du bord gauche du nœud par rapport à l'origine, le centre ou la fin "
+"de son contrôle parent. Il modifie la mise à jour de la marge gauche lorsque "
+"le nœud se déplace ou change la taille. Vous pouvez utiliser une des "
+"constantes de [enum Anchor] suivant les besoins."
#: doc/classes/Control.xml
msgid ""
@@ -20957,6 +21563,10 @@ msgid ""
"moves or changes size. You can use one of the [enum Anchor] constants for "
"convenience."
msgstr ""
+"L'ancre du bord droit du nœud par rapport à l'origine, le centre ou la fin "
+"de son contrôle parent. Il modifie la mise à jour de la marge droite lorsque "
+"le nœud se déplace ou change la taille. Vous pouvez utiliser une des "
+"constantes de [enum Anchor] suivant les besoins."
#: doc/classes/Control.xml
msgid ""
@@ -20964,6 +21574,10 @@ msgid ""
"parent control. It changes how the top margin updates when the node moves or "
"changes size. You can use one of the [enum Anchor] constants for convenience."
msgstr ""
+"L'ancre du bord du haut du nœud par rapport à l'origine, le centre ou la fin "
+"de son contrôle parent. Il modifie la mise à jour de la marge supérieure "
+"lorsque le nœud se déplace ou change la taille. Vous pouvez utiliser une des "
+"constantes de [enum Anchor] suivant les besoins."
#: doc/classes/Control.xml
msgid ""
@@ -21065,6 +21679,10 @@ msgid ""
"grow if its horizontal minimum size is changed to be greater than its "
"current size, as the control always has to be at least the minimum size."
msgstr ""
+"Control la direction sur l'axe horizontal selon lequel le contrôle doit "
+"croître si sa taille minimale horizontale est modifiée pour être supérieure "
+"à sa taille actuelle, car le contrôle doit toujours avoir au moins sa taille "
+"minimale."
#: doc/classes/Control.xml
msgid ""
@@ -21072,6 +21690,10 @@ msgid ""
"if its vertical minimum size is changed to be greater than its current size, "
"as the control always has to be at least the minimum size."
msgstr ""
+"Control la direction sur l'axe vertical selon lequel le contrôle doit "
+"croître si sa taille minimale verticale est changée pour être supérieure à "
+"sa taille actuelle, car le contrôle doit toujours avoir au moins sa taille "
+"minimale."
#: doc/classes/Control.xml
msgid ""
@@ -21124,6 +21746,11 @@ msgid ""
"handling. The viewport first hides the modal and after marks the input as "
"handled."
msgstr ""
+"Active quand l'entrée doit se propager lorsque vous fermez le contrôle en "
+"tant que modale.\n"
+"Si [code]false[/code], arrête le traitement de l'événement lors de la "
+"manipulation de l'événement d'entrée de la fenêtre d'affichage. La fenêtre "
+"d'affichage cache d'abord la modale et après marque l'entrée comme traitée."
#: doc/classes/Control.xml
msgid ""
@@ -21217,12 +21844,18 @@ msgid ""
"to this control's rectangle. If [code]true[/code], parts of a child which "
"would be visibly outside of this control's rectangle will not be rendered."
msgstr ""
+"Active quand le rendu des [CanvasItem] enfants doit être limité au rectangle "
+"engobant de ce contrôle. Si [code]true[/code], des parties des enfants qui "
+"seraient normalement visibles en-dehors de ce rectangle des contrôles seront "
+"cachées."
#: doc/classes/Control.xml
msgid ""
"The node's global position, relative to the world (usually to the top-left "
"corner of the window)."
msgstr ""
+"La position globale du nœud, par rapport au coordonnées globales "
+"(généralement au coin haut-gauche de la fenêtre)."
#: doc/classes/Control.xml
msgid ""
@@ -21231,6 +21864,11 @@ msgid ""
"this size, even if its content is smaller. If it's set to (0, 0), the node "
"sizes automatically to fit its content, be it a texture or child nodes."
msgstr ""
+"La taille minimale du rectangle englobant. Si vous le fixez à une valeur "
+"supérieure à (0, 0), le rectangle englobant du nœud aura toujours au moins "
+"cette taille, même si son contenu est plus petit. Si cette taille est à (0, "
+"0), le nœud sera redimensionné automatiquement pour s'adapter à son contenu, "
+"qu'il s'agisse d'une texture ou d'un nœud enfant."
#: doc/classes/Control.xml
msgid ""
@@ -21239,6 +21877,10 @@ msgid ""
"around this pivot. Set this property to [member rect_size] / 2 to pivot "
"around the Control's center."
msgstr ""
+"Par défaut, et le pivot du nœud est son coin supérieur gauche. Lorsque vous "
+"modifiez son [member rect_rotation] ou [member rect_scale], il tournera ou "
+"changera d'échelle autour de ce pivot. Définir cette propriété à [member "
+"rect_size] / 2 permet de pivoter autour du centre du contrôle."
#: doc/classes/Control.xml
msgid ""
@@ -21246,12 +21888,17 @@ msgid ""
"rectangle's top-left corner. The property is not affected by [member "
"rect_pivot_offset]."
msgstr ""
+"La position du nœud, par rapport à son parent. Elle correspond au coin "
+"supérieur gauche du rectangle. La propriété n'est pas affectée par [member "
+"rect_pivot_offset]."
#: doc/classes/Control.xml
msgid ""
"The node's rotation around its pivot, in degrees. See [member "
"rect_pivot_offset] to change the pivot's position."
msgstr ""
+"La rotation du nœud autour de son pivot, en degrés. Voir [member "
+"rect_pivot_offset] pour modifier la position du pivot."
#: doc/classes/Control.xml
msgid ""
@@ -21291,6 +21938,8 @@ msgid ""
"The size of the node's bounding rectangle, in pixels. [Container] nodes "
"update this property automatically."
msgstr ""
+"La taille du rectangle englobant du nœud, en pixels. Les nœuds [Container] "
+"mettent à jour cette propriété automatiquement."
#: doc/classes/Control.xml
msgid ""
@@ -21298,6 +21947,9 @@ msgid ""
"on the X axis. Use one of the [enum SizeFlags] constants to change the "
"flags. See the constants to learn what each does."
msgstr ""
+"Signale au [Container] parent qu'il devrait redimensionner et placer le nœud "
+"sur l'axe X. Utilisez l'une des constantes [enum SizeFlags] pour changer les "
+"drapeaux. Voyez les constantes pour apprendre ce que chacun fait."
#: doc/classes/Control.xml
msgid ""
@@ -21307,6 +21959,11 @@ msgid ""
"its neighbour a ratio of 1, this node will take two thirds of the available "
"space."
msgstr ""
+"Si le nœud et au moins un de ses voisins utilisent le drapeau de taille "
+"[constant SIZE_EXPAND], le [Container] parent le laissera prendre plus ou "
+"moins d'espace selon cette propriété. Si ce nœud a un rapport d'étirement de "
+"2 et son voisin un rapport de 1, ce nœud prendra les deux tiers (deux fois "
+"plus que l'autre) de l'espace disponible."
#: doc/classes/Control.xml
msgid ""
@@ -21314,12 +21971,17 @@ msgid ""
"on the Y axis. Use one of the [enum SizeFlags] constants to change the "
"flags. See the constants to learn what each does."
msgstr ""
+"Signale au [Container] parent qu'il devrait redimensionner et placer le nœud "
+"sur l'axe Y. Utilisez l'une des constantes [enum SizeFlags] pour changer les "
+"drapeaux. Voyez les constantes pour apprendre ce que chacun fait."
#: doc/classes/Control.xml
msgid ""
"Changing this property replaces the current [Theme] resource this node and "
"all its [Control] children use."
msgstr ""
+"Changer cette propriété remplace la ressource [Theme] actuelle que ce nœud "
+"et tous ses [Contrôle] enfants utilisent."
#: doc/classes/Control.xml
msgid ""
@@ -21388,6 +22050,12 @@ msgid ""
"at least until the mouse is moved to reach the parent's [code]Rect[/code] "
"area."
msgstr ""
+"Émis lorsque la souris entre dans le [code]Rect[/code] du contrôle, à "
+"condition que l'événement l'atteigne.\n"
+"[b]Note :[/b] [signal mouse_entered] ne sera pas émis si la souris entre "
+"dans un nœud [Control] enfant avant d'entrer dans le [code]Rect[/code], au "
+"moins jusqu'à ce que la souris soit déplacée pour atteindre le [code]Rect[/"
+"code] du parent."
#: doc/classes/Control.xml
msgid ""
@@ -21428,6 +22096,8 @@ msgid ""
"Emitted when one of the size flags changes. See [member "
"size_flags_horizontal] and [member size_flags_vertical]."
msgstr ""
+"Émis lorsque l'un des drapeaux de taille change. Voir [member "
+"size_flags_horizontal] et [member size_flags_vertical]."
#: doc/classes/Control.xml
msgid "The node cannot grab focus. Use with [member focus_mode]."
@@ -21446,11 +22116,16 @@ msgid ""
"The node can grab focus on mouse click or using the arrows and the Tab keys "
"on the keyboard. Use with [member focus_mode]."
msgstr ""
+"Le nœud peut obtenir le focus lors d'un clic de souris ou en utilisant les "
+"flèches et la touche de tabulation du clavier. À utiliser avec [member "
+"focus_mode]."
#: doc/classes/Control.xml
msgid ""
"Sent when the node changes size. Use [member rect_size] to get the new size."
msgstr ""
+"Envoyé quand le nœud change de taille. Utilisez [member rect_size] pour "
+"obtenir la nouvelle taille."
#: doc/classes/Control.xml
msgid "Sent when the mouse pointer enters the node."
@@ -21474,28 +22149,38 @@ msgid ""
"control. Happens when you call one of the [code]add_*_override[/code] "
"methods."
msgstr ""
+"Envoyé lorsque le [member theme] du nœud change, juste avant que Godot ne "
+"redessine le contrôle. Ça arrive quand vous appelez l'une des méthodes "
+"[code]add_*_override[/code]."
#: doc/classes/Control.xml
msgid "Sent when an open modal dialog closes. See [method show_modal]."
msgstr ""
+"Envoyé quand un dialogue modal ouvert se ferme. Voir [method show_modal]."
#: doc/classes/Control.xml
msgid ""
"Sent when this node is inside a [ScrollContainer] which has begun being "
"scrolled."
msgstr ""
+"Envoyé quand ce nœud est à l'intérieur d'un [ScrollContainer] qui a commencé "
+"à défilé."
#: doc/classes/Control.xml
msgid ""
"Sent when this node is inside a [ScrollContainer] which has stopped being "
"scrolled."
msgstr ""
+"Envoyé quand ce nœud est à l'intérieur d'un [ScrollContainer] qui a cessé de "
+"défilé."
#: doc/classes/Control.xml
msgid ""
"Show the system's arrow mouse cursor when the user hovers the node. Use with "
"[member mouse_default_cursor_shape]."
msgstr ""
+"Affiche le curseur système de la souris quand l'utilisateur survole le nœud. "
+"À utiliser avec [member mouse_default_cursor_shape]."
#: doc/classes/Control.xml
msgid ""
@@ -21623,72 +22308,98 @@ msgid ""
"Show the system's vertical split mouse cursor when the user hovers the node. "
"On Windows, it's the same as [constant CURSOR_VSIZE]."
msgstr ""
+"Affiche le curseur système de la souris avec un séparateur vertical lorsque "
+"l'utilisateur survole le nœud. Sur Windows, il est identique à [constant "
+"CURSOR_VSIZE]."
#: doc/classes/Control.xml
msgid ""
"Show the system's horizontal split mouse cursor when the user hovers the "
"node. On Windows, it's the same as [constant CURSOR_HSIZE]."
msgstr ""
+"Affiche le curseur système de la souris avec un séparateur horizontal "
+"lorsque l'utilisateur survole le nœud. Sur Windows, il est identique à "
+"[constant CURSOR_HSIZE]."
#: doc/classes/Control.xml
msgid ""
"Show the system's help mouse cursor when the user hovers the node, a "
"question mark."
msgstr ""
+"Affiche le curseur système de la souris pour l'aide lorsque l'utilisateur "
+"survole le nœud, avec un point d'interrogation."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the top-left of the parent control's bounds. Use with "
"[method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres jusqu'au coin gauche supérieur du rectangle "
+"englobant du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the top-right of the parent control's bounds. Use with "
"[method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres jusqu'au coin droit du rectangle englobant du "
+"contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the bottom-left of the parent control's bounds. Use "
"with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres jusqu'au coin bas-gauche du rectangle "
+"englobant du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the bottom-right of the parent control's bounds. Use "
"with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres jusqu'au coin bas-droit du rectangle englobant "
+"du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the center of the left edge of the parent control's "
"bounds. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres au centre du bord gauche du rectangle "
+"englobant du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the center of the top edge of the parent control's "
"bounds. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres au centre du bord supérieur du rectangle "
+"englobant du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the center of the right edge of the parent control's "
"bounds. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres au centre du bord droit du rectangle englobant "
+"du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the center of the bottom edge of the parent control's "
"bounds. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres au centre du bord du bas du rectangle "
+"englobant du contrôle parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to the center of the parent control's bounds. Use with "
"[method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres au centre du rectangle englobant de contrôle parent. "
+"À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21696,6 +22407,10 @@ msgid ""
"becomes relative to the left edge and the top margin relative to the top "
"left corner of the node's parent. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres sur le bord gauche du contrôle parent. La marge "
+"gauche devient alors relative au bord gauche et à la marge supérieure par "
+"rapport au coin supérieur gauche du nœud parent). À utiliser avec [méthod "
+"set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21704,6 +22419,11 @@ msgid ""
"edge, and the right margin relative to the top right corner of the node's "
"parent. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres sur le bord supérieur du contrôle parent. La "
+"marge gauche devient alors par rapport au coin supérieur gauche, à la marge "
+"supérieure par rapport au bord supérieur, et à la marge droite par rapport "
+"au coin supérieur droit du nœud parent . À utiliser avec [méthod "
+"set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21711,6 +22431,10 @@ msgid ""
"becomes relative to the right edge and the top margin relative to the top "
"right corner of the node's parent. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres au bord droit du contrôle parent. La marge droite "
+"devient alors par rapport au bord droit et à la marge supérieure par rapport "
+"au coin supérieur droit du nœud parent. À utiliser avec [méthod "
+"set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21719,18 +22443,26 @@ msgid ""
"the bottom edge, and the right margin relative to the bottom right corner of "
"the node's parent. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres au bord inférieur du contrôle parent. La marge gauche "
+"devient alors par rapport au coin inférieur gauche, à la marge inférieure "
+"par rapport au bord inférieur, et à la marge droite par rapport au coin "
+"inférieur droit du nœud parent. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to a vertical line that cuts the parent control in half. "
"Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres sur une ligne verticale qui coupe le contrôle parent "
+"en deux. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
"Snap all 4 anchors to a horizontal line that cuts the parent control in "
"half. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise les 4 ancres sur une ligne horizontale qui coupe le contrôle "
+"parent en deux. À utiliser avec [méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21739,6 +22471,11 @@ msgid ""
"parent control. This is equivalent to the \"Full Rect\" layout option in the "
"editor. Use with [method set_anchors_preset]."
msgstr ""
+"Magnétise toutes les 4 ancres aux angles respectifs du contrôle parent. "
+"Réglez toutes les 4 marges à 0 après avoir appliqué ce préréglage et le "
+"[Control] s'adaptera à son contrôle parent. Ceci est équivalent à l'option "
+"de mise en page \"Rectangle complet\" dans l'éditeur. À utiliser avec "
+"[méthod set_anchors_preset]."
#: doc/classes/Control.xml
msgid "The control will be resized to its minimum size."
@@ -21762,6 +22499,9 @@ msgid ""
"the available space without pushing any other node. Use with [member "
"size_flags_horizontal] and [member size_flags_vertical]."
msgstr ""
+"Signale au [Container] parent d'étendre les limites de ce nœud pour remplir "
+"tout l'espace disponible sans pousser un autre nœud. À utiliser avec [member "
+"size_flags_horizontal] et [member size_flags_vertical]."
#: doc/classes/Control.xml
msgid ""
@@ -21771,12 +22511,19 @@ msgid ""
"size_flags_stretch_ratio]. Use with [member size_flags_horizontal] and "
"[member size_flags_vertical]."
msgstr ""
+"Signale au [Container] parent de laisser ce nœud prendre tout l'espace "
+"disponible sur l'axe spécifié. Si plusieurs nœuds voisins sont prêts à "
+"s'étendre, ils partagent l'espace en fonction de leur rapport d'étirement. "
+"Voir [member size_flags_stretch_ratio]. À utiliser avec [member "
+"size_flags_horizontal] et [member size_flags_vertical]."
#: doc/classes/Control.xml
msgid ""
"Sets the node's size flags to both fill and expand. See the 2 constants "
"above for more information."
msgstr ""
+"Définit les drapeaux de taille du nœud pour à la fois remplir et s'étendre. "
+"Voir les 2 constantes ci-dessus pour plus d'informations."
#: doc/classes/Control.xml
msgid ""
@@ -21882,6 +22629,10 @@ msgid ""
"variables, like [member anchor_left]. To change all 4 anchors at once, use "
"[method set_anchors_preset]."
msgstr ""
+"Magnétise l'un des 4 côtés d'ancrage à l'origine de l'ancrage [code]Rect[/"
+"code], en haut à gauche. Utilisez-le avec l'une des variables membres "
+"[code]anchor_[* /code], comme [member anchor_left]. Pour modifier les 4 "
+"ancres à la fois, utilisez [method set_anchors_preset]."
#: doc/classes/Control.xml
msgid ""
@@ -21890,6 +22641,10 @@ msgid ""
"member variables, like [member anchor_left]. To change all 4 anchors at "
"once, use [method set_anchors_preset]."
msgstr ""
+"Magnétise l'un des 4 côtés d'ancrage à l'extrémité de l'extrémité "
+"[code]Rect[/code], en bas à droite. Utilisez-le avec l'une des variables "
+"membres [code]anchor_[* /code], comme [member anchor_left]. Pour modifier "
+"les 4 ancres à la fois, utilisez [method set_anchors_preset]."
#: doc/classes/ConvexPolygonShape.xml
msgid "Convex polygon shape for 3D physics."
@@ -22110,7 +22865,6 @@ msgstr "L'amortissement varie le long de cette [Curve]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
-#, fuzzy
msgid "Damping randomness ratio."
msgstr "Ratio d’amortissement aléatoire."
@@ -22139,6 +22893,8 @@ msgid ""
"Sets the [Color]s to modulate particles by when using [constant "
"EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS]."
msgstr ""
+"Définit les [Color] pour moduler les particules en utilisant [constant "
+"EMISSION_SHAPE_POINTS] ou [constant EMISSION_SHAPE_DIRECTED_POINTS]."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid ""
@@ -22153,6 +22909,9 @@ msgid ""
"Sets the initial positions to spawn particles when using [constant "
"EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS]."
msgstr ""
+"Définit les positions initiales pour les particules créées en utilisant "
+"[constant EMISSION_SHAPE_POINTS] ou [constant "
+"EMISSION_SHAPE_DIRECTED_POINTS]."
#: doc/classes/CPUParticles.xml
msgid ""
@@ -22172,6 +22931,8 @@ msgid ""
"The inner radius for the ring shaped emitter when using [constant "
"EMISSION_SHAPE_RING]."
msgstr ""
+"Le rayon intérieur de l'émetteur en anneau quand définit à [constant "
+"EMISSION_SHAPE_RING]."
#: doc/classes/CPUParticles.xml
msgid ""
@@ -22404,6 +23165,9 @@ msgid ""
"Each particle's initial direction range from [code]+spread[/code] to [code]-"
"spread[/code] degrees. Applied to X/Z plane and Y/Z planes."
msgstr ""
+"La direction initiale de chaque particule dans l'intervalle de "
+"[code]+spread[/code] à [code]-spread[/code] degrés. Appliquée aux plans sur "
+"X/Z et aux plans sur Y/Z."
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -22633,6 +23397,8 @@ msgid ""
"The sphere's radius if [member emission_shape] is set to [constant "
"EMISSION_SHAPE_SPHERE]."
msgstr ""
+"Le rayon de la sphère si [member emission_shape] est [constant "
+"EMISSION_SHAPE_SPHERE]."
#: doc/classes/CPUParticles2D.xml doc/classes/Particles.xml
#: doc/classes/Particles2D.xml
@@ -22682,6 +23448,8 @@ msgid ""
"Particles will be emitted on the surface of a sphere flattened to two "
"dimensions."
msgstr ""
+"Les particules seront émises à la surface d'une sphère aplatie en deux "
+"dimensions."
#: doc/classes/CPUParticles2D.xml
msgid "Particles will be emitted in the area of a rectangle."
@@ -22778,6 +23546,11 @@ msgid ""
"string-comparison-with-double-hmac-strategy]this blog post[/url] for more "
"information."
msgstr ""
+"Compare deux [PoolByteArray] pour l'égalité sans fuite temporelle "
+"d'informations afin de prévenir les attaques temporelles.\n"
+"Voir [url=https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-"
+"string-comparison-with-double-hmac-strategy]ce blog[/url] pour plus "
+"d'informations."
#: doc/classes/Crypto.xml
msgid ""
@@ -22816,6 +23589,8 @@ msgid ""
"Generates an RSA [CryptoKey] that can be used for creating self-signed "
"certificates and passed to [method StreamPeerSSL.accept_stream]."
msgstr ""
+"Génère une [CryptoKey] RSA qui peut être utilisé pour créer des certificats "
+"autosignés et transmis à [method StreamPeerSSL.accept_stream]"
#: doc/classes/Crypto.xml
msgid ""
@@ -22991,7 +23766,6 @@ msgid ""
msgstr ""
#: modules/csg/doc_classes/CSGCylinder.xml
-#, fuzzy
msgid "A CSG Cylinder shape."
msgstr "Une forme de cylindre CSG."
@@ -23113,12 +23887,18 @@ msgid ""
"shape. If [code]false[/code] the top half of the material is repeated every "
"step of the extrusion."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], par défaut, la moitié "
+"supérieure du [member material] est étirée sur toute la longueur de la forme "
+"extrudée. Si [code]false[/code] la partie supérieure du matériau est répétée "
+"à chaque étape de l'extrusion."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"When [member mode] is [constant MODE_PATH], the path interval or ratio of "
"path points to extrusions."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], l'intervalle de chemin ou le "
+"rapport de chemin pointe vers les extrusions."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23126,6 +23906,10 @@ msgid ""
"interval should be by distance ([constant PATH_INTERVAL_DISTANCE]) or "
"subdivision fractions ([constant PATH_INTERVAL_SUBDIVIDE])."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], cela déterminera si "
+"l'intervalle doit être suivant la distance ([constant "
+"PATH_INTERVAL_DISTANCE]) ou suivant une fraction des sous-divisions "
+"([constant PATH_INTERVAL_SUBDIVIDE])."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23133,6 +23917,9 @@ msgid ""
"the path are joined, by adding an extrusion between the last and first "
"points of the path."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], si [code]true[/code] les "
+"extrémités du chemin sont jointes, en ajoutant une extrusion entre le "
+"dernier et le premier points du chemin."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23140,24 +23927,34 @@ msgid ""
"[Transform] of the [CSGPolygon] is used as the starting point for the "
"extrusions, not the [Transform] of the [member path_node]."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], si [code]true[/code] la "
+"[Transform] du [CSGPolygon] est utilisée comme point de départ pour les "
+"extrusions, et non pas la [Transform] du [member path_node]."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"When [member mode] is [constant MODE_PATH], the location of the [Path] "
"object used to extrude the [member polygon]."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], l'emplacement de l'objet "
+"[Path] utilisé pour extruder le [member polygon]."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"When [member mode] is [constant MODE_PATH], the [enum PathRotation] method "
"used to rotate the [member polygon] as it is extruded."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], la méthode [enum "
+"PathRotation] utilisée pour faire pivoter le [member polygon] selon son "
+"extrusion."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"When [member mode] is [constant MODE_PATH], extrusions that are less than "
"this angle, will be merged together to reduce polygon count."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], les extrusions qui sont "
+"inférieures à cet angle seront fusionnés pour réduire le nombre de polygones."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23165,6 +23962,10 @@ msgid ""
"path, in meters, the texture coordinates will tile. When set to 0, texture "
"coordinates will match geometry exactly with no tiling."
msgstr ""
+"Lorsque [member mode] est [constant MODE_PATH], c'est la distance le long du "
+"chemin, en mètres, que les coordonnées de texture seront répétées. Quand à "
+"0, les coordonnées de texture correspondront exactement à la géométrie sans "
+"répétition."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23175,6 +23976,12 @@ msgid ""
"[b]Note:[/b] If only 1 or 2 points are defined in [member polygon], no mesh "
"will be generated."
msgstr ""
+"Le tableau de points qui définit le polygone 2D extrudé. Cela peut être un "
+"polygone convexe ou concave avec 3 points ou plus. Le polygone ne doit "
+"[i]pas[/i] avoir de bords qui sont des intersections. Sinon, la "
+"triangulation échouera et aucun maillage ne sera généré.\n"
+"[b]Note :[/b] Si seulement 1 ou 2 points sont définis dans [member polygon], "
+"aucun maillage ne sera généré."
#: modules/csg/doc_classes/CSGPolygon.xml
#, fuzzy
@@ -23216,6 +24023,9 @@ msgid ""
"[b]Note:[/b] Requires the path's Z coordinates to continually decrease to "
"ensure viable shapes."
msgstr ""
+"La forme [member polygon] n'a pas pivoté.\n"
+"[b]Note :[/b] Nécessite que les coordonnées Z du chemin diminuent en "
+"continue pour assurer des formes viables."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23224,12 +24034,17 @@ msgid ""
"[b]Note:[/b] Requires the path's Z coordinates to continually decrease to "
"ensure viable shapes."
msgstr ""
+"La forme [member polygon] est pivotée le long du chemin, mais elle n'est pas "
+"pivotée autour de l'axe du chemin.\n"
+"[b]Note :[/b] Nécessite que les coordonnées Z du chemin diminuent en "
+"continue pour assurer des formes viables."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"The [member polygon] shape follows the path and its rotations around the "
"path axis."
msgstr ""
+"La forme [member polygon] suit le chemin et pivote autour de l'axe du chemin."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
@@ -23237,12 +24052,17 @@ msgid ""
"will determine the distance, in meters, each interval of the path will "
"extrude."
msgstr ""
+"Lorsque [member mode] est défini à [constant MODE_PATH], [member "
+"path_interval] déterminera la distance, en mètres, entre chaque intervalle "
+"où le chemin s'extrudera."
#: modules/csg/doc_classes/CSGPolygon.xml
msgid ""
"When [member mode] is set to [constant MODE_PATH], [member path_interval] "
"will subdivide the polygons along the path."
msgstr ""
+"Lorsque [member mode] est défini [constant MODE_PATH], [member "
+"path_interval] divisera les polygones le long du chemin."
#: modules/csg/doc_classes/CSGPrimitive.xml
msgid "Base class for CSG primitives."
@@ -23304,12 +24124,16 @@ msgid ""
"Sets individual bits on the layer mask. Use this if you only need to change "
"one layer's value."
msgstr ""
+"Définit des bits individuels sur le masque de calque. Utilisez ceci si vous "
+"n'avez besoin que de changer de calque."
#: modules/csg/doc_classes/CSGShape.xml doc/classes/SoftBody.xml
msgid ""
"Sets individual bits on the collision mask. Use this if you only need to "
"change one layer's value."
msgstr ""
+"Définit des bits individuels sur le masque de collision. Utilisez ceci si "
+"vous n'avez besoin que de changer de calque."
#: modules/csg/doc_classes/CSGShape.xml
msgid ""
@@ -23624,6 +24448,16 @@ msgid ""
"this, increase [member subdivide_depth], [member subdivide_height] and "
"[member subdivide_width] until you no longer notice UV jittering."
msgstr ""
+"Générer un cuboïde [PrimitiveMesh] aligné sur les axes.\n"
+"La projection des UV du cube est disposée selon une disposition de 3×2 qui "
+"permet de placer une texture sur chaque face individuellement. Pour "
+"appliquer la même texture sur toutes les faces, modifiez la propriété UV du "
+"matériau actif à [code]Vector3(3, 2, 1)[/code].\n"
+"[b]Note :[/b] Lors de l'utilisation d'une grande texture [CubeMesh] (par "
+"exemple pour le sol), vous pouvez tomber sur des problèmes de jittering de "
+"l'UV suivant l'angle de la caméra. Pour résoudre cela, augmentez [member "
+"subdivide_depth], [member subdivide_height] et [member subdivide_width] "
+"jusqu'à ce que vous ne remarquez plus le jittering de l'UV."
#: doc/classes/CubeMesh.xml
msgid "Size of the cuboid mesh."
@@ -23632,14 +24466,17 @@ msgstr "Taille du maillage cuboïde."
#: doc/classes/CubeMesh.xml
msgid "Number of extra edge loops inserted along the Z axis."
msgstr ""
+"Le nombre de boucles de bord supplémentaires insérées le long de l'axe Z."
#: doc/classes/CubeMesh.xml
msgid "Number of extra edge loops inserted along the Y axis."
msgstr ""
+"Le nombre de boucles de bord supplémentaires insérées le long de l'axe Y."
#: doc/classes/CubeMesh.xml
msgid "Number of extra edge loops inserted along the X axis."
msgstr ""
+"Le nombre de boucles de bord supplémentaires insérées le long de l'axe X."
#: doc/classes/CullInstance.xml
msgid "Parent of all nodes that can be culled by the Portal system."
@@ -23753,6 +24590,9 @@ msgid ""
"ranges between [code]0[/code] and [code]1[/code] on the Y axis and positions "
"points relative to the [code]0.5[/code] Y position."
msgstr ""
+"Une courbe qui peut être sauvegardée et réutilisée pour d'autres objets. Par "
+"défaut, elle va de [code]0[/code] à [code]1[/code] selon l'axe Y et les "
+"positions sont relatives à la position [code]0.5[/code] de l'axe Y."
#: doc/classes/Curve.xml
msgid ""
@@ -23762,6 +24602,12 @@ msgid ""
"assignments to the [code]*_tangent[/code] angle if [code]*_mode[/code] is "
"set to [constant TANGENT_FREE]."
msgstr ""
+"Ajoute un point à la courbe. Pour chaque côté, si le [code]*_mode[/code] est "
+"[constant TANGENT_LINEAR], l'angle [code]*_tangent[/code] (en degrés) "
+"utilise la pente de la courbe définie par rapport à la demi-distance du "
+"point adjacent. Permet des spécifier des tangentes personnalisées avec "
+"[code]*_tangent[/code] si [code]*_mode[/code] est défini à [constant "
+"TANGENT_FREE]."
#: doc/classes/Curve.xml
msgid "Recomputes the baked cache of points for the curve."
@@ -23772,6 +24618,8 @@ msgid ""
"Removes points that are closer than [code]CMP_EPSILON[/code] (0.00001) units "
"to their neighbor on the curve."
msgstr ""
+"Retire les points qui sont plus proches que [code]CMP_EPSILON[/code] "
+"(0.00001) unités à leur voisin sur la courbe."
#: doc/classes/Curve.xml doc/classes/Curve2D.xml doc/classes/Curve3D.xml
msgid "Removes all points from the curve."
@@ -23816,6 +24664,8 @@ msgid ""
"Returns the Y value for the point that would exist at the X position "
"[code]offset[/code] along the curve."
msgstr ""
+"Retourne la valeur Y pour un point qui existerait à la position X "
+"[code]offset[/code] le long de la courbe."
#: doc/classes/Curve.xml
msgid ""
@@ -23823,6 +24673,9 @@ msgid ""
"[code]offset[/code] along the curve using the baked cache. Bakes the curve's "
"points if not already baked."
msgstr ""
+"Retourne la valeur Y pour un point qui existerait à la position X "
+"[code]offset[/code] le long de la courbe en utilisant le cache précalculé. "
+"Précalcule les points de la courbe suivante si ça n'a pas déjà été fait."
#: doc/classes/Curve.xml
msgid "Removes the point at [code]index[/code] from the curve."
@@ -23897,6 +24750,8 @@ msgid ""
"The curve calculates the tangent on this side of the point as the slope "
"halfway towards the adjacent point."
msgstr ""
+"La courbe calcule la tangente de ce côté du point comme la pente avec la "
+"demi-distance du point adjacent."
#: doc/classes/Curve.xml
msgid "The total number of available tangent modes."
@@ -24696,13 +25551,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -24714,8 +25573,12 @@ msgstr ""
"Voir [enum ShadowDepthRange]."
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
-msgstr "Distance maximale pour les fractionnements d’ombre."
+msgid ""
+"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)."
+msgstr ""
#: doc/classes/DirectionalLight.xml
msgid "The light's shadow rendering algorithm. See [enum ShadowMode]."
@@ -24732,23 +25595,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -33073,9 +33936,8 @@ msgstr ""
"[Gradient]."
#: doc/classes/GradientTexture2D.xml
-#, fuzzy
msgid "Gradient-filled 2D texture."
-msgstr "Texture remplie de gradients."
+msgstr "Texture de gradient 2D."
#: doc/classes/GradientTexture2D.xml
msgid ""
@@ -34350,9 +35212,8 @@ msgstr ""
"valeur redimensionnera [member map_data]."
#: doc/classes/HFlowContainer.xml
-#, fuzzy
msgid "Horizontal flow container."
-msgstr "Conteneur de boîte horizontale."
+msgstr "Conteneur de flux horizontal."
#: doc/classes/HFlowContainer.xml
msgid "Horizontal version of [FlowContainer]."
@@ -36022,7 +36883,6 @@ msgstr ""
"max_redirects]."
#: doc/classes/Image.xml
-#, fuzzy
msgid "Image datatype."
msgstr "Type de données d’image."
@@ -37515,7 +38375,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -38155,10 +39018,11 @@ msgstr "Type d’évènement d’entrée pour les évènements de mouvement de s
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -38527,6 +39391,13 @@ msgstr ""
"automatiquement."
#: doc/classes/InterpolatedCamera.xml
+#, fuzzy
+msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+"La méthode de mise à jour de la camera. Voir [enum Camera2DProcessMode]."
+
+#: doc/classes/InterpolatedCamera.xml
msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
@@ -42519,37 +43390,32 @@ msgstr ""
"un tableau des sommets donc ce tableau doit être présent."
#: doc/classes/Mesh.xml
-#, fuzzy
msgid "Mesh array contains normals."
msgstr "Un maillage de points contient des normales."
#: doc/classes/Mesh.xml
-#, fuzzy
msgid "Mesh array contains tangents."
msgstr "Un maillage de points contient des tangentes."
#: doc/classes/Mesh.xml
-#, fuzzy
msgid "Mesh array contains colors."
-msgstr "Un maillage de points contient les couleurs."
+msgstr "Un maillage de points contient des couleurs."
#: doc/classes/Mesh.xml
-#, fuzzy
msgid "Mesh array contains UVs."
-msgstr "Un maillage de points contient les UV."
+msgstr "Un maillage de points contient des UV."
#: doc/classes/Mesh.xml
msgid "Mesh array contains second UV."
-msgstr "Un maillage de points contient les UV secondaires."
+msgstr "Un maillage de points contient des UV secondaires."
#: doc/classes/Mesh.xml
-#, fuzzy
msgid "Mesh array contains bones."
-msgstr "Un maillage de points contient les os."
+msgstr "Un maillage de points contient des os."
#: doc/classes/Mesh.xml
msgid "Mesh array contains bone weights."
-msgstr "Un maillage de points contient les poids des os."
+msgstr "Un maillage de points contient des poids d'os."
#: doc/classes/Mesh.xml
msgid "Mesh array uses indices."
@@ -44554,7 +45420,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -44667,6 +45533,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -47349,7 +48223,7 @@ msgstr ""
#: doc/classes/Node2D.xml
msgid "Local [Transform2D]."
-msgstr "[Transform2D] local."
+msgstr "[Transform2D] locale."
#: doc/classes/Node2D.xml
msgid ""
@@ -51953,7 +52827,7 @@ msgstr "Représente la taille de l'énumération [enum Monitor]."
#: doc/classes/PHashTranslation.xml
msgid "Optimized translation."
-msgstr "Translation optimisée."
+msgstr "Traduction optimisée."
#: doc/classes/PHashTranslation.xml
msgid ""
@@ -59564,8 +60438,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -68718,10 +69592,32 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
-"Formate la chaîne de caractères en remplaçant toutes les occurences de "
-"[code]placeholder[/code] par [code]values[/code]."
#: doc/classes/String.xml
msgid "If the string is a valid file path, returns the base directory name."
@@ -69445,9 +70341,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -70427,12 +71325,12 @@ msgstr ""
"[code]tab_idx[/code], le rendant non-interactif."
#: doc/classes/TabContainer.xml
-#, fuzzy
msgid ""
"If [code]hidden[/code] is [code]true[/code], hides the tab at index "
"[code]tab_idx[/code], making it disappear from the tab area."
msgstr ""
-"Retourne [code]true[/code] si la piste à l'index [code]idx[/code] est active."
+"Si [code]hidden[/code] est [code]true[/code], cache l'onglet à l'index "
+"[code]tab_idx[/code], se faisait disparaitre de l'aire des onglets."
#: doc/classes/TabContainer.xml
msgid "Sets an icon for the tab at index [code]tab_idx[/code]."
@@ -71236,6 +72134,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr "Si [code]true[/code], un clic droit affiche le menu contextuel."
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Si [code]true[/code], la valeur peut être sélectionnée et modifiée."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -74138,13 +75041,13 @@ msgstr ""
"matrice. L'axe [code]axis[/code] doit être normalisé."
#: doc/classes/Transform.xml
-#, fuzzy
msgid ""
"Returns a copy of the transform with its basis and origin scaled by the "
"given [code]scale[/code] factor, using matrix multiplication."
msgstr ""
-"Met à l'échelle le transform par le facteur d'échelle donné, en utilisant la "
-"multiplication matricielle."
+"Retourne une copie de la transformation avec sa base et son origine mis à "
+"l'échelle par le facteur [code]scale[/code], en utilisant la multiplication "
+"matricielle."
#: doc/classes/Transform.xml doc/classes/Transform2D.xml
msgid ""
@@ -77426,9 +78329,8 @@ msgid ""
msgstr ""
#: doc/classes/VFlowContainer.xml
-#, fuzzy
msgid "Vertical flow container."
-msgstr "Conteneur vertical."
+msgstr "Conteneur de flux vertical."
#: doc/classes/VFlowContainer.xml
msgid "Vertical version of [FlowContainer]."
@@ -77976,9 +78878,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -78011,8 +78914,12 @@ msgstr ""
"l'arrière-plan de manière transparente."
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
-msgstr "Le mode de rendu de la fenêtre d'affichage."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
+msgstr ""
#: doc/classes/Viewport.xml
msgid ""
diff --git a/doc/translations/gl.po b/doc/translations/gl.po
index 39d5ab2f2b..3273cd8f98 100644
--- a/doc/translations/gl.po
+++ b/doc/translations/gl.po
@@ -12140,10 +12140,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19425,13 +19427,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19441,7 +19447,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19458,23 +19468,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29820,7 +29830,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30394,10 +30407,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30720,6 +30734,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36120,7 +36139,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36231,6 +36250,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49810,8 +49837,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58180,7 +58207,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58777,9 +58828,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60316,6 +60369,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66390,9 +66447,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66421,7 +66479,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/hi.po b/doc/translations/hi.po
index a104e2ae6d..361c131a40 100644
--- a/doc/translations/hi.po
+++ b/doc/translations/hi.po
@@ -12139,10 +12139,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19424,13 +19426,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19440,7 +19446,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19457,23 +19467,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29819,7 +29829,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30393,10 +30406,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30719,6 +30733,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36119,7 +36138,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36230,6 +36249,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49809,8 +49836,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58179,7 +58206,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58776,9 +58827,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60315,6 +60368,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66389,9 +66446,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66420,7 +66478,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/hu.po b/doc/translations/hu.po
index 280424c8c0..2732b7b56a 100644
--- a/doc/translations/hu.po
+++ b/doc/translations/hu.po
@@ -12158,10 +12158,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19443,13 +19445,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19459,7 +19465,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19476,23 +19486,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29838,7 +29848,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30412,10 +30425,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30738,6 +30752,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36138,7 +36157,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36249,6 +36268,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49828,8 +49855,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58198,7 +58225,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58795,9 +58846,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60334,6 +60387,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66408,9 +66465,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66439,7 +66497,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/id.po b/doc/translations/id.po
index 2f741d544d..efc379cffd 100644
--- a/doc/translations/id.po
+++ b/doc/translations/id.po
@@ -12551,10 +12551,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19838,13 +19840,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19854,7 +19860,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19871,23 +19881,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30244,7 +30254,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30818,10 +30831,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31144,6 +31158,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36564,7 +36583,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36676,6 +36695,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50277,8 +50304,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58650,7 +58677,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59247,9 +59298,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60790,6 +60843,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66865,9 +66922,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66896,7 +66954,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/is.po b/doc/translations/is.po
index 4dd42d807e..bdd631ef18 100644
--- a/doc/translations/is.po
+++ b/doc/translations/is.po
@@ -12139,10 +12139,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19424,13 +19426,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19440,7 +19446,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19457,23 +19467,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29819,7 +29829,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30393,10 +30406,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30719,6 +30733,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36119,7 +36138,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36230,6 +36249,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49809,8 +49836,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58179,7 +58206,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58776,9 +58827,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60315,6 +60368,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66389,9 +66446,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66420,7 +66478,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/it.po b/doc/translations/it.po
index 9157d2ecc0..3d9cd62b30 100644
--- a/doc/translations/it.po
+++ b/doc/translations/it.po
@@ -13170,10 +13170,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -20563,13 +20565,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20579,7 +20585,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20596,23 +20606,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -31009,7 +31019,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31584,10 +31597,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31914,6 +31928,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -37368,7 +37387,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -37481,6 +37500,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -51136,8 +51163,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -59529,7 +59556,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -60126,9 +60177,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61688,6 +61741,13 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+"Se [code] vero [/code], i nodi figli sono ordinati, altrimenti l'ordinamento "
+"è disabilitato."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67830,9 +67890,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67864,7 +67925,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ja.po b/doc/translations/ja.po
index 75d4179693..8ace2ec0c8 100644
--- a/doc/translations/ja.po
+++ b/doc/translations/ja.po
@@ -15107,10 +15107,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -22561,13 +22563,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -22577,7 +22583,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -22594,23 +22604,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -33071,7 +33081,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -33645,10 +33658,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -33977,6 +33991,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -39508,7 +39527,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -39623,6 +39642,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -53345,8 +53372,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -62077,7 +62104,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -62674,9 +62725,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -64251,6 +64304,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "[code]true[/code] ã§ã‚れã°ã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã¯ä¸­å¤®ã«ãªã‚Šã¾ã™ã€‚"
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -70432,9 +70490,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -70464,7 +70523,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ko.po b/doc/translations/ko.po
index a30a93f652..bd808074b9 100644
--- a/doc/translations/ko.po
+++ b/doc/translations/ko.po
@@ -15,12 +15,13 @@
# whatthesamuel <alex01763@gmail.com>, 2021.
# 한수현 <shh1473@ajou.ac.kr>, 2022.
# vrSono <global.sonogong@gmail.com>, 2022.
+# 김태우 <ogosengi3@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-13 03:39+0000\n"
-"Last-Translator: vrSono <global.sonogong@gmail.com>\n"
+"PO-Revision-Date: 2022-06-29 10:30+0000\n"
+"Last-Translator: 김태우 <ogosengi3@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ko/>\n"
"Language: ko\n"
@@ -28,7 +29,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -88,7 +89,7 @@ msgstr "(%s를 ë®ì–´ì”€)"
#: doc/tools/make_rst.py
msgid "Default"
-msgstr ""
+msgstr "기본값"
#: doc/tools/make_rst.py
msgid "Setter"
@@ -96,7 +97,7 @@ msgstr "Setter"
#: doc/tools/make_rst.py
msgid "value"
-msgstr ""
+msgstr "ê°’"
#: doc/tools/make_rst.py
msgid "Getter"
@@ -12316,10 +12317,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19650,13 +19653,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19666,7 +19673,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19683,23 +19694,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30129,7 +30140,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30703,10 +30717,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31030,6 +31045,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36462,7 +36482,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36575,6 +36595,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50318,8 +50346,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58692,7 +58720,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59289,9 +59341,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60836,6 +60890,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "ë§¤ê°œë³€ìˆ˜ì˜ ì½”ì‚¬ì¸ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66936,9 +66995,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66967,7 +67027,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/lt.po b/doc/translations/lt.po
index 1139bf4f82..2de21d55b3 100644
--- a/doc/translations/lt.po
+++ b/doc/translations/lt.po
@@ -12149,10 +12149,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19434,13 +19436,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19450,7 +19456,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19467,23 +19477,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29829,7 +29839,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30403,10 +30416,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30729,6 +30743,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36129,7 +36148,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36240,6 +36259,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49819,8 +49846,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58189,7 +58216,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58786,9 +58837,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60325,6 +60378,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66399,9 +66456,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66430,7 +66488,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/lv.po b/doc/translations/lv.po
index 627035b696..45e3188446 100644
--- a/doc/translations/lv.po
+++ b/doc/translations/lv.po
@@ -12154,10 +12154,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19439,13 +19441,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19455,7 +19461,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19472,23 +19482,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29837,7 +29847,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30411,10 +30424,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30737,6 +30751,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36137,7 +36156,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36248,6 +36267,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49827,8 +49854,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58197,7 +58224,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58794,9 +58845,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60333,6 +60386,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66407,9 +66464,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66438,7 +66496,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/mr.po b/doc/translations/mr.po
index d4e8907c1d..b943c79052 100644
--- a/doc/translations/mr.po
+++ b/doc/translations/mr.po
@@ -12137,10 +12137,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19422,13 +19424,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19438,7 +19444,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19455,23 +19465,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29817,7 +29827,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30391,10 +30404,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30717,6 +30731,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36117,7 +36136,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36228,6 +36247,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49807,8 +49834,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58177,7 +58204,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58774,9 +58825,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60313,6 +60366,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66387,9 +66444,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66418,7 +66476,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/nb.po b/doc/translations/nb.po
index 9aa8c17200..53fca58f26 100644
--- a/doc/translations/nb.po
+++ b/doc/translations/nb.po
@@ -12149,10 +12149,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19434,13 +19436,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19450,7 +19456,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19467,23 +19477,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29829,7 +29839,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30403,10 +30416,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30729,6 +30743,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36129,7 +36148,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36240,6 +36259,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49819,8 +49846,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58189,7 +58216,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58786,9 +58837,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60325,6 +60378,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66399,9 +66456,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66430,7 +66488,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ne.po b/doc/translations/ne.po
index f129446976..24062d3cff 100644
--- a/doc/translations/ne.po
+++ b/doc/translations/ne.po
@@ -12137,10 +12137,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19422,13 +19424,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19438,7 +19444,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19455,23 +19465,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29817,7 +29827,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30391,10 +30404,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30717,6 +30731,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36117,7 +36136,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36228,6 +36247,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49807,8 +49834,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58177,7 +58204,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58774,9 +58825,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60313,6 +60366,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66387,9 +66444,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66418,7 +66476,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/nl.po b/doc/translations/nl.po
index 7a96e774df..b2066a5491 100644
--- a/doc/translations/nl.po
+++ b/doc/translations/nl.po
@@ -12206,10 +12206,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19491,13 +19493,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19507,7 +19513,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19524,23 +19534,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29889,7 +29899,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30463,10 +30476,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30789,6 +30803,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36189,7 +36208,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36300,6 +36319,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49879,8 +49906,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58250,7 +58277,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58847,9 +58898,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60386,6 +60439,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66460,9 +66517,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66491,7 +66549,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/pl.po b/doc/translations/pl.po
index 640cfea1c8..b28e575320 100644
--- a/doc/translations/pl.po
+++ b/doc/translations/pl.po
@@ -12651,10 +12651,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19963,13 +19965,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19979,7 +19985,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19996,23 +20006,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30398,7 +30408,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30972,10 +30985,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31302,6 +31316,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36769,7 +36788,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36882,6 +36901,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50526,8 +50553,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58915,7 +58942,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59512,9 +59563,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61063,6 +61116,13 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+"Jeśli [code]true[/code], potomne węzły są sortowane. W innym przypadku jest "
+"wyłączone."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67169,9 +67229,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67203,7 +67264,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/pt.po b/doc/translations/pt.po
index 54c5f5f2ef..99537cdd6b 100644
--- a/doc/translations/pt.po
+++ b/doc/translations/pt.po
@@ -9,12 +9,13 @@
# Renu <ifpilucas@gmail.com>, 2022.
# Diogo Gomes <dgomes@graphnode.com>, 2022.
# El_ExpertPlayer <xpertnathan37@gmail.com>, 2022.
+# Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-13 03:39+0000\n"
-"Last-Translator: El_ExpertPlayer <xpertnathan37@gmail.com>\n"
+"PO-Revision-Date: 2022-06-29 10:31+0000\n"
+"Last-Translator: Esdras Caleb Oliveira Silva <acheicaleb@gmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/pt/>\n"
"Language: pt\n"
@@ -22,7 +23,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -78,7 +79,7 @@ msgstr "Herdado por:"
#: doc/tools/make_rst.py
msgid "(overrides %s)"
-msgstr ""
+msgstr "(recopiar %s)"
#: doc/tools/make_rst.py
msgid "Default"
@@ -86,7 +87,7 @@ msgstr "Padrão"
#: doc/tools/make_rst.py
msgid "Setter"
-msgstr "Definidor"
+msgstr "Setter"
#: doc/tools/make_rst.py
msgid "value"
@@ -94,13 +95,13 @@ msgstr "valor"
#: doc/tools/make_rst.py
msgid "Getter"
-msgstr "Buscador"
+msgstr "Getter"
#: doc/tools/make_rst.py
msgid ""
"This method should typically be overridden by the user to have any effect."
msgstr ""
-"Este método normalmente deve ser substituído pelo usuário para ter algum "
+"Este método normalmente deve ser reescrito pelo usuário para que tenha algum "
"efeito."
#: doc/tools/make_rst.py
@@ -907,7 +908,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two values by the factor defined in "
"[code]weight[/code]. To perform interpolation, [code]weight[/code] should be "
@@ -927,20 +927,25 @@ msgid ""
"To perform eased interpolation with [method lerp], combine it with [method "
"ease] or [method smoothstep]."
msgstr ""
-"Interpola linearmente entre dois valores através de um valor normalizado. "
-"Este método é o oposto do método [method inverse_lerp].\n"
+"Interpola linearmente entre dois valores pelo fator definido em "
+"[code]weight[/code]. Para realizar a interpolação, [code]weight[/code] deve "
+"estar entre [code]0.0[/code] e [code]1.0[/code] (inclusive). No entanto, "
+"valores fora desse intervalo são permitidos e podem ser usados para realizar "
+"[i]extrapolação[/i].\n"
"Se os argumentos [code]from[/code] e [code]to[/code] forem do tipo [int] ou "
-"[float], o retorno é um valor do tipo [float].\n"
-"Se ambos são vetores de mesmo tipo ([Vector2], [Vector3] ou [Color]), o "
-"valor retornado será do mesmo tipo ([code]lerp[/code] então chamará o método "
-"[code]lerp[/code] do tipo de vetor em questão).\n"
+"[float], o valor de retorno será um [float].\n"
+"Se ambos forem do mesmo tipo de vetor ([Vector2], [Vector3] ou [Color]), o "
+"valor de retorno será do mesmo tipo ([code]lerp[/code] então chama o método "
+"[code]linear_interpolate[/code] do tipo de vetor).\n"
"[codeblock]\n"
-"lerp(0, 4, 0.75) # Retorna 3.0\n"
-"lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Retorna Vector2(2, 3.5)\n"
-"[/codeblock]"
+"lerp(0, 4, 0,75) # Retorna 3,0\n"
+"lerp(Vetor2(1, 5), Vetor2(3, 2), 0.5) # Retorna Vetor2(2, 3.5)\n"
+"[/codeblock]\n"
+"Veja também [method inverse_lerp] que realiza o inverso desta operação. Para "
+"realizar a interpolação facilitada com [method lerp], combine-o com [method "
+"easy] ou [method smoothstep]."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two angles (in radians) by a normalized "
"value.\n"
@@ -963,10 +968,12 @@ msgid ""
"example, [code]lerp_angle(0, PI, weight)[/code] lerps counter-clockwise, "
"while [code]lerp_angle(0, PI + 5 * TAU, weight)[/code] lerps clockwise."
msgstr ""
-"Faz a interpolação linear entre dois ângulos (em radianos) por um valor "
+"Interpola linearmente entre dois ângulos (em radianos) por um valor "
"normalizado.\n"
-"Semelhante à [method lerp], mas faz a interpolação corretamente quando os "
-"ângulos passam através de [constant @GDScript.TAU].\n"
+"Semelhante a [method lerp], mas interpola corretamente quando os ângulos "
+"envolvem [constant @GDScript.TAU]. Para realizar a interpolação facilitada "
+"com [method lerp_angle], combine-o com [method easy] ou [method "
+"smoothstep].\n"
"[codeblock]\n"
"extends Sprite\n"
"var elapsed = 0.0\n"
@@ -975,7 +982,14 @@ msgstr ""
" var max_angle = deg2rad(90.0)\n"
" rotation = lerp_angle(min_angle, max_angle, elapsed)\n"
" elapsed += delta\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Nota:[/b] Este método lê o caminho mais curto entre [code]from[/code] e "
+"[code]to[/code]. No entanto, quando esses dois ângulos estão aproximadamente "
+"[code]PI + k * TAU[/code] separados para qualquer inteiro [code]k[/code], "
+"não é óbvio de que maneira eles interpretam devido a erros de precisão de "
+"ponto flutuante. Por exemplo, [code]lerp_angle(0, PI, weight)[/code] lê no "
+"sentido anti-horário, enquanto [code]lerp_angle(0, PI + 5 * TAU, weight)[/"
+"code] lê no sentido horário."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1463,7 +1477,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns a random floating point value between [code]from[/code] and "
"[code]to[/code] (both endpoints inclusive).\n"
@@ -1472,12 +1485,12 @@ msgid ""
"[/codeblock]\n"
"[b]Note:[/b] This is equivalent to [code]randf() * (to - from) + from[/code]."
msgstr ""
-"Intervalo aleatório, retorna qualquer número real entre [code]from[/code] e "
-"[code]to[/code].\n"
+"Retorna um valor de ponto flutuante aleatório entre [code]from[/code] e "
+"[code]to[/code] (ambos os endpoints inclusive).\n"
"[codeblock]\n"
-"prints(rand_range(0, 1), rand_range(0, 1)) # Imprime por exemplo 0.135591 "
-"0.405263\n"
-"[/codeblock]"
+"prints(rand_range(0, 1), rand_range(0, 1)) # Prints e.g. 0.135591 0.405263\n"
+"[/codeblock]\n"
+"[b]Nota:[/b] Isso é equivalente a [code]randf() * (to - from) + from[/code]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -4579,9 +4592,8 @@ msgstr ""
#: doc/classes/AABB.xml doc/classes/Rect2.xml doc/classes/Vector2.xml
#: doc/classes/Vector3.xml
-#, fuzzy
msgid "Vector math"
-msgstr "Vetor utilizado para matemática 2D."
+msgstr "Matemática vetorial"
#: doc/classes/AABB.xml doc/classes/Rect2.xml doc/classes/Vector2.xml
#: doc/classes/Vector3.xml
@@ -5798,9 +5810,8 @@ msgstr ""
#: doc/classes/AnimationNodeOneShot.xml doc/classes/AnimationNodeOutput.xml
#: doc/classes/AnimationNodeTimeScale.xml
#: doc/classes/AnimationNodeTransition.xml
-#, fuzzy
msgid "AnimationTree"
-msgstr "Nó de animação."
+msgstr "AnimationTree"
#: doc/classes/AnimationNodeAdd3.xml doc/classes/AnimationNodeAnimation.xml
#: doc/classes/AnimationNodeBlend2.xml
@@ -6493,9 +6504,8 @@ msgid ""
msgstr ""
#: doc/classes/AnimationPlayer.xml
-#, fuzzy
msgid "Animation tutorial index"
-msgstr "Nó de animação."
+msgstr "Ãndice do tutorial de animação"
#: doc/classes/AnimationPlayer.xml
msgid ""
@@ -6784,9 +6794,8 @@ msgid ""
msgstr ""
#: doc/classes/AnimationTree.xml
-#, fuzzy
msgid "Using AnimationTree"
-msgstr "Reseta este [AnimationTreePlayer]."
+msgstr "Usando AnimationTree"
#: doc/classes/AnimationTree.xml
msgid "Manually advance the animations by the specified time (in seconds)."
@@ -12958,10 +12967,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -13749,9 +13760,8 @@ msgstr ""
"camada -1 ou abaixo)."
#: doc/classes/CanvasLayer.xml
-#, fuzzy
msgid "Canvas layers"
-msgstr "Camada para desenhar no ecrã."
+msgstr "Camadas de tela"
#: doc/classes/CanvasLayer.xml
msgid "Returns the RID of the canvas used by this layer."
@@ -14821,9 +14831,8 @@ msgstr ""
#: doc/classes/Physics2DDirectSpaceState.xml
#: doc/classes/PhysicsDirectBodyState.xml
#: doc/classes/PhysicsDirectSpaceState.xml doc/classes/RigidBody.xml
-#, fuzzy
msgid "Physics introduction"
-msgstr "Interpolação cúbica."
+msgstr "Introdução à física"
#: doc/classes/CollisionShape.xml
msgid ""
@@ -16390,9 +16399,8 @@ msgid "GUI tutorial index"
msgstr ""
#: doc/classes/Control.xml
-#, fuzzy
msgid "Control node gallery"
-msgstr "Tecla Control."
+msgstr "Galeria de *nós* de controle"
#: doc/classes/Control.xml
msgid "All GUI Demos"
@@ -20292,13 +20300,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20308,7 +20320,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20325,23 +20341,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30704,7 +30720,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31278,10 +31297,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31608,6 +31628,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -37046,7 +37071,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -37159,6 +37184,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -38441,7 +38474,7 @@ msgstr ""
#: doc/classes/Node.xml
msgid "Nodes and Scenes"
-msgstr ""
+msgstr "Nós e Cenas"
#: doc/classes/Node.xml
msgid "All Demos"
@@ -49310,68 +49343,67 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 3."
-msgstr ""
+msgstr "Nome opcional para a camada 3 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 30."
-msgstr ""
+msgstr "Nome opcional para a camada 30 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 31."
-msgstr ""
+msgstr "Nome opcional para a camada 31 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 32."
-msgstr ""
+msgstr "Nome opcional para a camada 32 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 4."
-msgstr ""
+msgstr "Nome opcional para a camada 4 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 5."
-msgstr ""
+msgstr "Nome opcional para a camada 5 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 6."
-msgstr ""
+msgstr "Nome opcional para a camada 6 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 7."
-msgstr ""
+msgstr "Nome opcional para a camada 7 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 8."
-msgstr ""
+msgstr "Nome opcional para a camada 8 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D physics layer 9."
-msgstr ""
+msgstr "Nome opcional para a camada 9 de física 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 1."
-msgstr "Nome opcional para a camada 1 da renderização 3D."
+msgstr "Nome opcional para a camada 1 de renderização 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 10."
-msgstr "Nome opcional para a camada 10 da renderização 3D."
+msgstr "Nome opcional para a camada 10 de renderização 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 11."
-msgstr "Nome opcional para a camada 11 da renderização 3D."
+msgstr "Nome opcional para a camada 11 de renderização 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 12."
-msgstr "Nome opcional para a camada 12 da renderização 3D."
+msgstr "Nome opcional para a camada 12 de renderização 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 13."
-msgstr "Nome opcional para a camada 13 da renderização 3D."
+msgstr "Nome opcional para a camada 13 de renderização 3D."
#: doc/classes/ProjectSettings.xml
-#, fuzzy
msgid "Optional name for the 3D render layer 14."
-msgstr "Nome opcional para a camada 14 da renderização 3D"
+msgstr "Nome opcional para a camada 14 de renderização 3D."
#: doc/classes/ProjectSettings.xml
msgid "Optional name for the 3D render layer 15."
@@ -49434,38 +49466,53 @@ msgid ""
"The locale to fall back to if a translation isn't available in a given "
"language. If left empty, [code]en[/code] (English) will be used."
msgstr ""
+"A localidade para retornar se uma tradução não estiver disponível em um "
+"determinado idioma. Se deixado em branco, [code]en[/code] (inglês) será "
+"usado."
#: doc/classes/ProjectSettings.xml
msgid ""
"If non-empty, this locale will be used when running the project from the "
"editor."
msgstr ""
+"Se não estiver vazio, essa localidade será usada ao executar o projeto a "
+"partir do editor."
#: doc/classes/ProjectSettings.xml
msgid "If [code]true[/code], logs all output to files."
-msgstr ""
+msgstr "Se [code]true[/code], registra todas os resultados nos arquivos."
#: doc/classes/ProjectSettings.xml
msgid ""
"Desktop override for [member logging/file_logging/enable_file_logging], as "
"log files are not readily accessible on mobile/Web platforms."
msgstr ""
+"Substituição da área de trabalho para [member logging/file_logging/"
+"enable_file_logging], pois os arquivos de log não são facilmente acessíveis "
+"em plataformas móveis/Web."
#: doc/classes/ProjectSettings.xml
msgid ""
"Path to logs within the project. Using an [code]user://[/code] path is "
"recommended."
msgstr ""
+"Caminho para logs dentro do projeto. Recomenda se utilizar um caminho "
+"[code]user://[/code]."
#: doc/classes/ProjectSettings.xml
msgid "Specifies the maximum amount of log files allowed (used for rotation)."
msgstr ""
+"Especifica a quantidade máxima de arquivos de log permitidos (usados para "
+"rotação)."
#: doc/classes/ProjectSettings.xml
msgid ""
"Godot uses a message queue to defer some function calls. If you run out of "
"space on it (you will see an error), you can increase the size here."
msgstr ""
+"Godot usa uma fila de mensagens para adiar algumas chamadas de função. Se "
+"você ficar sem espaço nela (você verá um erro), você pode aumentar o tamanho "
+"aqui."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49474,6 +49521,11 @@ msgid ""
"on threads. If servers get stalled too often when loading resources in a "
"thread, increase this number."
msgstr ""
+"Isso é usado por servidores quando usado no modo multi-threading (servidores "
+"e visual). Os RIDs são pré-alocados para evitar a interrupção do servidor "
+"que os solicita em encadeamentos. Se os servidores ficarem paralisados com "
+"muita frequência ao carregar recursos em um encadeamento, aumente esse "
+"número."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49486,6 +49538,14 @@ msgid ""
"in the editor, which also includes C# [code]tool[/code] scripts running "
"within the editor as well as editor plugin code."
msgstr ""
+"A política a ser usada para exceções Mono (C#) não tratadas. O padrão "
+"\"Terminate Application\" sai do projeto assim que uma exceção não tratada é "
+"lançada. Em vez disso, \"Log Error\" registra uma mensagem de erro no "
+"console e não interromperá a execução do projeto quando uma exceção não "
+"tratada for lançada.\n"
+"[b]Observação:[/b] A política de exceção não tratada é sempre definida como "
+"\"Erro de log\" no editor, que também inclui scripts C# [code]tool[/code] "
+"executados no editor, bem como o código do plug-in do editor."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49493,42 +49553,57 @@ msgid ""
"map_set_cell_height].\n"
"[b]Note:[/b] Currently not implemented."
msgstr ""
+"Altura de célula padrão para mapas de navegação 2D. Consulte [método "
+"Navigation2DServer.map_set_cell_height].\n"
+"[b]Observação:[/b] atualmente não implementado."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default cell size for 2D navigation maps. See [method Navigation2DServer."
"map_set_cell_size]."
msgstr ""
+"Tamanho de célula padrão para mapas de navegação 2D. Consulte [method "
+"Navigation2DServer.map_set_cell_size]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default edge connection margin for 2D navigation maps. See [method "
"Navigation2DServer.map_set_edge_connection_margin]."
msgstr ""
+"Margem de conexão de borda padrão para mapas de navegação 2D. Consulte "
+"[method Navigation2DServer.map_set_edge_connection_margin]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default cell height for 3D navigation maps. See [method NavigationServer."
"map_set_cell_height]."
msgstr ""
+"Altura de célula padrão para mapas de navegação 3D. Consulte [method "
+"NavigationServer.map_set_cell_height]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default cell size for 3D navigation maps. See [method NavigationServer."
"map_set_cell_size]."
msgstr ""
+"Tamanho de célula padrão para mapas de navegação 3D. Consulte [method "
+"NavigationServer.map_set_cell_size]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default edge connection margin for 3D navigation maps. See [method "
"NavigationServer.map_set_edge_connection_margin]."
msgstr ""
+"Margem de conexão de borda padrão para mapas de navegação 3D. Consulte "
+"[method NavigationServer.map_set_edge_connection_margin]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Default map up vector for 3D navigation maps. See [method NavigationServer."
"map_set_up]."
msgstr ""
+"Vetor de mapa padrão para mapas de navegação 3D. Consulte [method "
+"NavigationServer.map_set_up]."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49536,6 +49611,9 @@ msgid ""
"Over this value, content is dropped. This helps not to stall the debugger "
"connection."
msgstr ""
+"Quantidade máxima de caracteres permitidos para enviar como saída do "
+"depurador. Acima desse valor, o conteúdo é descartado. Isso ajuda a não "
+"travar a conexão do depurador."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49543,6 +49621,9 @@ msgid ""
"Over this value, content is dropped. This helps not to stall the debugger "
"connection."
msgstr ""
+"Número máximo de erros permitidos a serem enviados como saída do depurador. "
+"Acima desse valor, o conteúdo é descartado. Isso ajuda a não travar a "
+"conexão do depurador."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49550,6 +49631,9 @@ msgid ""
"this value, content is dropped. This helps not to stall the debugger "
"connection."
msgstr ""
+"Quantidade máxima de mensagens permitidas para enviar como saída do "
+"depurador. Acima desse valor, o conteúdo é descartado. Isso ajuda a não "
+"travar a conexão do depurador."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49557,6 +49641,9 @@ msgid ""
"Over this value, content is dropped. This helps not to stall the debugger "
"connection."
msgstr ""
+"Número máximo de avisos que podem ser enviados como saída do depurador. "
+"Acima desse valor, o conteúdo é descartado. Isso ajuda a não travar a "
+"conexão do depurador."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -49564,56 +49651,64 @@ msgid ""
"specified as a power of two). The default value [code]16[/code] is equal to "
"65,536 bytes. Over this size, data is dropped."
msgstr ""
+"Tamanho padrão do fluxo de pares de pacotes para desserializar dados Godot "
+"(em bytes, especificado como uma potência de dois). O valor padrão [code]16[/"
+"code] é igual a 65.536 bytes. Acima desse tamanho, os dados são descartados."
#: doc/classes/ProjectSettings.xml
msgid "Timeout (in seconds) for connection attempts using TCP."
-msgstr ""
+msgstr "Tempo limite (em segundos) para tentativas de conexão usando TCP."
#: doc/classes/ProjectSettings.xml
msgid "Maximum size (in kiB) for the [WebRTCDataChannel] input buffer."
-msgstr ""
+msgstr "Tamanho máximo (em kiB) para o buffer de entrada [WebRTCDataChannel]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum size (in kiB) for the [WebSocketClient] input buffer."
-msgstr ""
+msgstr "Tamanho máximo (em kiB) para o buffer de entrada [WebSocketClient]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum number of concurrent input packets for [WebSocketClient]."
msgstr ""
+"Número máximo de pacotes de entrada simultâneos para [WebSocketClient]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum size (in kiB) for the [WebSocketClient] output buffer."
-msgstr ""
+msgstr "Tamanho máximo (em kiB) para o buffer de saída [WebSocketClient]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum number of concurrent output packets for [WebSocketClient]."
-msgstr ""
+msgstr "Número máximo de pacotes de saída simultâneos para [WebSocketClient]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum size (in kiB) for the [WebSocketServer] input buffer."
-msgstr ""
+msgstr "Tamanho máximo (em kiB) para o buffer de entrada [WebSocketServer]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum number of concurrent input packets for [WebSocketServer]."
msgstr ""
+"Número máximo de pacotes de entrada simultâneos para [WebSocketServer]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum size (in kiB) for the [WebSocketServer] output buffer."
-msgstr ""
+msgstr "Tamanho máximo (em kiB) para o buffer de saída [WebSocketServer]."
#: doc/classes/ProjectSettings.xml
msgid "Maximum number of concurrent output packets for [WebSocketServer]."
-msgstr ""
+msgstr "Número máximo de pacotes de saída simultâneos para [WebSocketServer]."
#: doc/classes/ProjectSettings.xml
msgid ""
"Amount of read ahead used by remote filesystem. Higher values decrease the "
"effects of latency at the cost of higher bandwidth usage."
msgstr ""
+"Quantidade de leitura antecipada usada pelo sistema de arquivos remoto. "
+"Valores mais altos diminuem os efeitos da latência ao custo de maior uso de "
+"largura de banda."
#: doc/classes/ProjectSettings.xml
msgid "Page size used by remote filesystem (in bytes)."
-msgstr ""
+msgstr "Tamanho da página usado pelo sistema de arquivos remoto (em bytes)."
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -50756,8 +50851,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -59151,7 +59246,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59748,9 +59867,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61291,6 +61412,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Se [code]true[/code], o objeto é desenhado por cima do pai dele."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67385,9 +67511,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67416,7 +67543,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/pt_BR.po b/doc/translations/pt_BR.po
index b32492887a..b432963519 100644
--- a/doc/translations/pt_BR.po
+++ b/doc/translations/pt_BR.po
@@ -13209,10 +13209,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -20592,13 +20594,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20608,7 +20614,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20625,23 +20635,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -31043,7 +31053,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31617,10 +31630,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31951,6 +31965,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -37411,7 +37430,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -37525,6 +37544,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -51178,8 +51205,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -59588,7 +59615,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -60185,9 +60236,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61746,6 +61799,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Retorna [code]true[/code] se o script pode ser instanciado."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67861,9 +67919,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67895,7 +67954,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ro.po b/doc/translations/ro.po
index 260a63446f..068587e37a 100644
--- a/doc/translations/ro.po
+++ b/doc/translations/ro.po
@@ -12169,10 +12169,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19454,13 +19456,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19470,7 +19476,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19487,23 +19497,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29852,7 +29862,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30426,10 +30439,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30752,6 +30766,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36152,7 +36171,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36263,6 +36282,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49843,8 +49870,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58213,7 +58240,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58810,9 +58861,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60349,6 +60402,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66423,9 +66480,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66454,7 +66512,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/ru.po b/doc/translations/ru.po
index 36dbb7d50d..6455a611e5 100644
--- a/doc/translations/ru.po
+++ b/doc/translations/ru.po
@@ -48,12 +48,13 @@
# Bozhko Artyom Dmitrievich <jek_sun@mail.ru>, 2022.
# FuzzMix <fmwolfiechad@gmail.com>, 2022.
# МÐÐ69К <weblate@mah69k.net>, 2022.
+# Vadim Mitroshkin <Vadim7540@yandex.ru>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-08 06:47+0000\n"
-"Last-Translator: FuzzMix <fmwolfiechad@gmail.com>\n"
+"PO-Revision-Date: 2022-07-03 00:44+0000\n"
+"Last-Translator: Bozhko Artyom Dmitrievich <jek_sun@mail.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/ru/>\n"
"Language: ru\n"
@@ -62,7 +63,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -154,7 +155,8 @@ msgstr ""
#: doc/tools/make_rst.py
msgid ""
"This method accepts any number of arguments after the ones described here."
-msgstr "Этот метод принимает любое количеÑтво аргументов поÑле опиÑанных."
+msgstr ""
+"Этот метод принимает любое количеÑтво аргументов поÑле опиÑанных здеÑÑŒ."
#: doc/tools/make_rst.py
msgid "This method is used to construct a type."
@@ -533,7 +535,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Compares two values by checking their actual contents, recursing into any "
"[Array] or [Dictionary] up to its deepest level.\n"
@@ -559,9 +560,9 @@ msgstr ""
"- Ð”Ð»Ñ [code]null[/code], [code]int[/code], [code]float[/code], [code]String[/"
"code], [code]Object[/code] и [code]RID[/code], [code]deep_equal[/code] и "
"[code]==[/code] работают одинаково.\n"
-"- Ð”Ð»Ñ [code]Dictionary[/code], [code]==[/code] раÑÑматривает равенÑтво и "
-"только еÑли обе переменные указывают на один и тот же [code]Dictionary[/"
-"code], без рекурÑии или проÑмотра Ñодержимого вообще.\n"
+"- Ð”Ð»Ñ [code]Dictionary[/code], [code]==[/code] раÑÑматривает равенÑтво "
+"тогда, и только тогда, когда обе переменные указывают на один и тот же "
+"[code]Dictionary[/code], без рекурÑии или проÑмотра Ñодержимого вообще.\n"
"- Ð”Ð»Ñ [code]Array[/code], [code]==[/code] ÑчитаетÑÑ Ñ€Ð°Ð²ÐµÐ½Ñтвом тогда, и "
"только тогда, когда каждый Ñлемент в первом [code]Array[/code] равен "
"Ñлементу во втором [code]Array[/code], как Ñообщает [code]==[/code]. Это "
@@ -1006,7 +1007,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Linearly interpolates between two angles (in radians) by a normalized "
"value.\n"
@@ -1032,7 +1032,7 @@ msgstr ""
"Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑÑ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ð´Ð²ÑƒÐ¼Ñ ÑƒÐ³Ð»Ð°Ð¼Ð¸ (в радианах) по нормализованному "
"значению.\n"
"Ðналогично [методу lerp], но корректно интерполируетÑÑ, когда углы "
-"оборачивают вокруг [constant @GDScript.TAU]. Чтобы выполнить упрощенную "
+"оборачивают вокруг [конÑтанты @GDScript.TAU]. Чтобы выполнить упрощенную "
"интерполÑцию Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ [метода lerp_angle], объедините его Ñ [методом ease] "
"или [методом smoothstep].\n"
"[codeblock]\n"
@@ -1043,7 +1043,14 @@ msgstr ""
" var max_angle = deg2rad(90.0)\n"
" rotation = lerp_angle(min_angle, max_angle, elapsed)\n"
" elapsed += delta\n"
-"[/codeblock]"
+"[/codeblock]\n"
+"[b]Примечание:[/b] Этот метод проходит через кратчайший путь между "
+"[code]from[/code] и [code]to[/code]. Тем не менее, еÑли разница между Ñтими "
+"Ð´Ð²ÑƒÐ¼Ñ ÑƒÐ³Ð»Ð°Ð¼Ð¸ и любым целым чиÑлом [code]k[/code] приблизительно [code]PI + "
+"k * TAU[/code], неочевидно в какую Ñторону [/code]из-за ошибок в точноÑти "
+"чиÑел Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ точкой. Ðапример, [code]lerp_angle(0, PI, weight)[/code] "
+"оборачиваетÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð² чаÑовой Ñтрелки, а [code]lerp_angle(0, PI + 5 * TAU, "
+"weight)[/code] оборачиваетÑÑ Ð¿Ð¾ чаÑовой."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1292,7 +1299,6 @@ msgstr ""
"координат (оÑи X и Y)."
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the integer modulus of [code]a/b[/code] that wraps equally in "
"positive and negative.\n"
@@ -1314,28 +1320,21 @@ msgstr ""
"Возвращает целочиÑленный модуль [code]a/b[/code], который одинаково "
"переноÑитÑÑ ÐºÐ°Ðº в положительный, так и в отрицательный.\n"
"[codeblock]\n"
-"var i = -6\n"
-"while i < 5:\n"
-" prints(i, posmod(i, 3))\n"
-" i += 1\n"
+"for i in range(-3, 4):\n"
+" print(\"%2d %2d %2d\" % [i, i % 3, posmod(i, 3)])\n"
"[/codeblock]\n"
"Produces:\n"
"[codeblock]\n"
-"-6 0\n"
-"-5 1\n"
-"-4 2\n"
-"-3 0\n"
-"-2 1\n"
-"-1 2\n"
-"0 0\n"
-"1 1\n"
-"2 2\n"
-"3 0\n"
-"4 1\n"
+"-3 0 0\n"
+"-2 -2 1\n"
+"-1 -1 2\n"
+" 0 0 0\n"
+" 1 1 1\n"
+" 2 2 2\n"
+" 3 0 0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns the result of [code]base[/code] raised to the power of [code]exp[/"
"code].\n"
@@ -1346,7 +1345,7 @@ msgstr ""
"Возвращает результат Ð²Ð¾Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ñ‡Ð¸Ñла [code]x[/code] в Ñтепени [code]y[/"
"code].\n"
"[codeblock]\n"
-"pow(2, 5) # Возвращает 32\n"
+"pow(2, 5) # Возвращает 32.0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1525,7 +1524,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Converts an angle expressed in radians to degrees.\n"
"[codeblock]\n"
@@ -1534,7 +1532,7 @@ msgid ""
msgstr ""
"Преобразует угол, выраженный в радианах, в градуÑÑ‹.\n"
"[codeblock]\n"
-"rad2deg(0.523599) # Возвращает 30\n"
+"rad2deg(0.523599) # Возвращает 30.0\n"
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
@@ -1581,7 +1579,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Returns a random unsigned 32-bit integer. Use remainder to obtain a random "
"value in the interval [code][0, N - 1][/code] (where N is smaller than "
@@ -1660,6 +1657,44 @@ msgid ""
"3\n"
"[/codeblock]"
msgstr ""
+"Возвращает маÑÑив Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ð¼ диапазоном. [метод range] может быть вызван "
+"Ñ‚Ñ€ÐµÐ¼Ñ ÑпоÑобами:\n"
+"[code]range(n: int)[/code]: ÐачинаетÑÑ Ñ 0, увеличиваетÑÑ Ñ ÑˆÐ°Ð³Ð¾Ð¼ в 1 и "
+"оÑтанавливаетÑÑ [i]перед[/i] [code]n[/code]. Ðргумент [code]n[/code] Ñто "
+"[b]ÑкÑклюзив[/b].\n"
+"[code]range(b: int, n: int)[/code]: ÐачинаетÑÑ Ñ [code]b[/code], "
+"увеличиваетÑÑ Ñ ÑˆÐ°Ð³Ð¾Ð¼ в 1 и оÑтанавливаетÑÑ [i]перед[/i] [code]n[/code]. "
+"Ðргументы [code]b[/code] и [code]n[/code] Ñто [b]инклюзив[/b] и "
+"[b]ÑкÑклюзив[/b], ÑоответÑтвенно.\n"
+"[code]range(b: int, n: int, s: int)[/code]: ÐачинаетÑÑ Ñ [code]b[/code], "
+"увеличиваетÑÑ/уменьшаетÑÑ Ñ ÑˆÐ°Ð³Ð¾Ð¼ [code]s[/code], и оÑтанавливаетÑÑ "
+"[i]перед[/i] [code]n[/code]. Ðргументы [code]b[/code] и [code]n[/code] Ñто "
+"[b]инклюзив[/b] и [b]ÑкÑклюзив[/b], ÑоответÑтвенно. Ðргумент [code]s[/code] "
+"[b]может[/b] быть негативным, но не [code]0[/code]. ЕÑли [code]s[/code] Ñто "
+"[code]0[/code], будет выведено Ñообщение об ошибке.\n"
+"[метод range] преобразует вÑе аргументы в [int] перед обработкой.\n"
+"[b]Примечание:[/b] Возвращает пуÑтой маÑÑив, еÑли ни одно значение не "
+"удовлетворÑет ограничению на значение (e.g. [code]range(2, 5, -1)[/code] или "
+"[code]range(5, 5, 1)[/code]).\n"
+"Примеры:\n"
+"[codeblock]\n"
+"print(range(4)) # Prints [0, 1, 2, 3]\n"
+"print(range(2, 5)) # Prints [2, 3, 4]\n"
+"print(range(0, 6, 2)) # Prints [0, 2, 4]\n"
+"print(range(4, 1, -1)) # Prints [4, 3, 2]\n"
+"[/codeblock]\n"
+"Чтобы выполнить итерацию по [Array] в обратном порÑдке, иÑпользуйте:\n"
+"[codeblock]\n"
+"var array = [3, 6, 9]\n"
+"for i in range(array.size(), 0, -1):\n"
+" print(array[i - 1])\n"
+"[/codeblock]\n"
+"Вывод:\n"
+"[codeblock]\n"
+"9\n"
+"6\n"
+"3\n"
+"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -1676,7 +1711,6 @@ msgstr ""
"[/codeblock]"
#: modules/gdscript/doc_classes/@GDScript.xml
-#, fuzzy
msgid ""
"Rounds [code]s[/code] to the nearest whole number, with halfway cases "
"rounded away from zero.\n"
@@ -1687,11 +1721,14 @@ msgid ""
"[/codeblock]\n"
"See also [method floor], [method ceil], [method stepify], and [int]."
msgstr ""
-"ОкруглÑет [code]s[/code] к ближайшему целому чиÑлу, при Ñтом Ñередины "
-"округлÑÑŽÑ‚ÑÑ Ð¾Ñ‚ нулÑ.\n"
+"ОкруглÑет [code]s[/code] к ближайшему целому чиÑлу, при Ñтом 0.5 округлÑетÑÑ "
+"в большую Ñторону.\n"
"[codeblock]\n"
-"round(2.6) # Возвращает 3\n"
-"[/codeblock]"
+"a = round(2.49) # Возвращает 2.0\n"
+"a = round(2.5) # Возвращает 3.0\n"
+"a = round(2.51) # Возвращает 3.0\n"
+"[/codeblock]\n"
+"См. также[метод floor], [метод ceil], [метод stepify], и [int]."
#: modules/gdscript/doc_classes/@GDScript.xml
msgid ""
@@ -13799,10 +13836,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -21231,13 +21270,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -21247,7 +21290,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -21264,23 +21311,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -31684,7 +31731,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -32258,10 +32308,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -32586,6 +32637,11 @@ msgstr "ЕÑли [code]true[/code], текÑтура отражена по веÑ
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -38070,7 +38126,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -38183,6 +38239,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -51969,8 +52033,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -60441,7 +60505,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -61038,9 +61126,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -62598,6 +62688,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "ЕÑли [code]true[/code], текÑтура будет центрирована."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -68866,9 +68961,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -68898,7 +68994,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/sk.po b/doc/translations/sk.po
index 9fb9613f0d..4964bf3ce0 100644
--- a/doc/translations/sk.po
+++ b/doc/translations/sk.po
@@ -12140,10 +12140,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19425,13 +19427,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19441,7 +19447,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19458,23 +19468,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29823,7 +29833,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30397,10 +30410,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30723,6 +30737,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36123,7 +36142,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36234,6 +36253,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49813,8 +49840,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58183,7 +58210,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58780,9 +58831,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60319,6 +60372,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66393,9 +66450,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66424,7 +66482,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/sr_Cyrl.po b/doc/translations/sr_Cyrl.po
index 765c89be10..89efbf0d11 100644
--- a/doc/translations/sr_Cyrl.po
+++ b/doc/translations/sr_Cyrl.po
@@ -12151,10 +12151,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19436,13 +19438,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19452,7 +19458,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19469,23 +19479,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29834,7 +29844,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30408,10 +30421,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30734,6 +30748,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36134,7 +36153,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36245,6 +36264,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49824,8 +49851,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58194,7 +58221,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58791,9 +58842,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60330,6 +60383,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66404,9 +66461,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66435,7 +66493,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/sv.po b/doc/translations/sv.po
index 706b410d30..e562fe9d6f 100644
--- a/doc/translations/sv.po
+++ b/doc/translations/sv.po
@@ -12140,10 +12140,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19425,13 +19427,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19441,7 +19447,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19458,23 +19468,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29820,7 +29830,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30394,10 +30407,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30720,6 +30734,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36120,7 +36139,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36231,6 +36250,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49810,8 +49837,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58180,7 +58207,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58777,9 +58828,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60316,6 +60369,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66390,9 +66447,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66421,7 +66479,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/th.po b/doc/translations/th.po
index 68c0dd503a..097eae8507 100644
--- a/doc/translations/th.po
+++ b/doc/translations/th.po
@@ -12246,10 +12246,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19535,13 +19537,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19551,7 +19557,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19568,23 +19578,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29961,7 +29971,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30551,10 +30564,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30881,6 +30895,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36308,7 +36327,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36420,6 +36439,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50068,8 +50095,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58444,7 +58471,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59041,9 +59092,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60584,6 +60637,10 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66671,9 +66728,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66702,7 +66760,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/tl.po b/doc/translations/tl.po
index 4361ff7318..7473388512 100644
--- a/doc/translations/tl.po
+++ b/doc/translations/tl.po
@@ -12223,10 +12223,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19508,13 +19510,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19524,7 +19530,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19541,23 +19551,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29909,7 +29919,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30483,10 +30496,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30809,6 +30823,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36233,7 +36252,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36344,6 +36363,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -49926,8 +49953,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58296,7 +58323,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -58893,9 +58944,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60435,6 +60488,13 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+"Kung [code]true[/code], ang mga child nodes ay inaayos, kung hindi ang pag-"
+"so-sort ay hindi pinapagana."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66515,9 +66575,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66546,7 +66607,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/tr.po b/doc/translations/tr.po
index 01b71d7673..77fbf5f31a 100644
--- a/doc/translations/tr.po
+++ b/doc/translations/tr.po
@@ -18,12 +18,14 @@
# yigithan <yigithanermet38@gmail.com>, 2021.
# Yusuf Yavuzyigit <yusufyavuzyigit25@gmail.com>, 2021, 2022.
# Ramazan Aslan <legendraslan@gmail.com>, 2022.
+# paledega <paledega@yandex.ru>, 2022.
+# Yekez <yasintonge@gmail.com>, 2022.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-13 03:39+0000\n"
-"Last-Translator: Ramazan Aslan <legendraslan@gmail.com>\n"
+"PO-Revision-Date: 2022-07-03 00:45+0000\n"
+"Last-Translator: Yekez <yasintonge@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot-class-reference/tr/>\n"
"Language: tr\n"
@@ -31,7 +33,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: doc/tools/make_rst.py
msgid "Description"
@@ -83,7 +85,7 @@ msgstr "Miras:"
#: doc/tools/make_rst.py
msgid "Inherited By:"
-msgstr ""
+msgstr "Kalıtılan:"
#: doc/tools/make_rst.py
msgid "(overrides %s)"
@@ -91,19 +93,21 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "Default"
-msgstr ""
+msgstr "Varsayılan"
#: doc/tools/make_rst.py
+#, fuzzy
msgid "Setter"
-msgstr ""
+msgstr "Ayarlayıcı"
#: doc/tools/make_rst.py
msgid "value"
msgstr "deÄŸer"
#: doc/tools/make_rst.py
+#, fuzzy
msgid "Getter"
-msgstr ""
+msgstr "Alıcı"
#: doc/tools/make_rst.py
msgid ""
@@ -129,13 +133,15 @@ msgstr ""
#: doc/tools/make_rst.py
msgid "This method is used to construct a type."
-msgstr ""
+msgstr "Bu method bir veri tipi oluşturmak için kullanılır."
#: doc/tools/make_rst.py
msgid ""
"This method doesn't need an instance to be called, so it can be called "
"directly using the class name."
msgstr ""
+"Bu metod çağrılmak için bir örneklemeye ihtiyaç duymaz, bu yüzden doğrudan "
+"sınıf adı ile çağırılabilir."
#: doc/tools/make_rst.py
msgid ""
@@ -12925,10 +12931,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -20232,13 +20240,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20248,7 +20260,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -20265,23 +20281,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30657,7 +30673,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -31231,10 +31250,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31560,6 +31580,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -37003,7 +37028,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -37116,6 +37141,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50748,8 +50781,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -59131,7 +59164,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59728,9 +59785,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -61277,6 +61336,12 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr ""
+"Eğer [code]true[/code] ise düğümler sıraya sokulur, yoksa sıraya sokulmaz."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67369,9 +67434,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67402,7 +67468,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/uk.po b/doc/translations/uk.po
index e943465bca..fe1ac7f153 100644
--- a/doc/translations/uk.po
+++ b/doc/translations/uk.po
@@ -12302,10 +12302,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19604,13 +19606,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19620,7 +19626,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19637,23 +19647,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30019,7 +30029,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30593,10 +30606,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30920,6 +30934,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36354,7 +36373,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36467,6 +36486,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50086,8 +50113,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58462,7 +58489,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59059,9 +59110,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60607,6 +60660,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Повертає коÑÐ¸Ð½ÑƒÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66698,9 +66756,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66729,7 +66788,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/vi.po b/doc/translations/vi.po
index 81411cebb9..4dbfaf376a 100644
--- a/doc/translations/vi.po
+++ b/doc/translations/vi.po
@@ -12598,10 +12598,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19903,13 +19905,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19919,7 +19925,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19936,23 +19946,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -30317,7 +30327,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30891,10 +30904,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -31219,6 +31233,11 @@ msgstr "Nếu [code]true[/code] thì lật dá»c há»a tiết."
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36655,7 +36674,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36768,6 +36787,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50402,8 +50429,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58785,7 +58812,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59382,9 +59433,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60930,6 +60983,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "Nếu [code]true[/code], há»a tiết sẽ được căn ở trung tâm."
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -67026,9 +67084,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -67058,7 +67117,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/doc/translations/zh_CN.po b/doc/translations/zh_CN.po
index e39b32f496..2888f15fd1 100644
--- a/doc/translations/zh_CN.po
+++ b/doc/translations/zh_CN.po
@@ -62,7 +62,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine class reference\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
-"PO-Revision-Date: 2022-06-23 04:30+0000\n"
+"PO-Revision-Date: 2022-07-05 23:52+0000\n"
"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"godot-engine/godot-class-reference/zh_Hans/>\n"
@@ -5171,19 +5171,19 @@ msgstr ""
#: doc/classes/AnimatedSprite.xml doc/classes/SpriteBase3D.xml
msgid "If [code]true[/code], texture will be centered."
-msgstr "为 [code]true[/code] 时纹ç†å°†è¢«å±…中。"
+msgstr "如果为 [code]true[/code],纹ç†å°†è¢«å±…中。"
#: doc/classes/AnimatedSprite.xml doc/classes/Sprite.xml
#: doc/classes/SpriteBase3D.xml doc/classes/TextureButton.xml
#: doc/classes/TextureRect.xml
msgid "If [code]true[/code], texture is flipped horizontally."
-msgstr "为 [code]true[/code] 时纹ç†å°†è¢«æ°´å¹³ç¿»è½¬ã€‚"
+msgstr "如果为 [code]true[/code],纹ç†å°†è¢«æ°´å¹³ç¿»è½¬ã€‚"
#: doc/classes/AnimatedSprite.xml doc/classes/Sprite.xml
#: doc/classes/SpriteBase3D.xml doc/classes/TextureButton.xml
#: doc/classes/TextureRect.xml
msgid "If [code]true[/code], texture is flipped vertically."
-msgstr "为 [code]true[/code] 时纹ç†å°†è¢«åž‚直翻转。"
+msgstr "如果为 [code]true[/code],纹ç†å°†è¢«åž‚直翻转。"
#: doc/classes/AnimatedSprite.xml doc/classes/AnimatedSprite3D.xml
msgid "The displayed animation frame's index."
@@ -7945,7 +7945,7 @@ msgstr "该区域音频总线的å称。"
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid ""
"If [code]true[/code], the area's audio bus overrides the default audio bus."
-msgstr "为 [code]true[/code] 时该区域的音频总线将覆盖默认的音频总线。"
+msgstr "如果为 [code]true[/code],该区域的音频总线将覆盖默认的音频总线。"
#: doc/classes/Area.xml
msgid ""
@@ -7991,13 +7991,14 @@ msgstr ""
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid "If [code]true[/code], other monitoring areas can detect this area."
-msgstr "为 [code]true[/code] 时其他监测区域å¯ä»¥æ£€æµ‹åˆ°è¿™ä¸ªåŒºåŸŸã€‚"
+msgstr "如果为 [code]true[/code],其他监测区域å¯ä»¥æ£€æµ‹åˆ°è¿™ä¸ªåŒºåŸŸã€‚"
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid ""
"If [code]true[/code], the area detects bodies or areas entering and exiting "
"it."
-msgstr "为 [code]true[/code] 时该区域能够检测到进入和退出该区域的实体或区域。"
+msgstr ""
+"如果为 [code]true[/code],该区域能够检测到进入和退出该区域的实体或区域。"
#: doc/classes/Area.xml doc/classes/Area2D.xml
msgid "The area's priority. Higher priority areas are processed first."
@@ -8013,7 +8014,7 @@ msgstr ""
#: doc/classes/Area.xml
msgid "If [code]true[/code], the area applies reverb to its associated audio."
-msgstr "为 [code]true[/code] 时该区域会将混å“应用于其相关音频。"
+msgstr "如果为 [code]true[/code],该区域会将混å“应用于其相关音频。"
#: doc/classes/Area.xml
msgid "The reverb bus name to use for this area's associated audio."
@@ -12370,7 +12371,7 @@ msgstr "åœæ­¢éŸ³é¢‘。"
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
msgid "If [code]true[/code], audio plays when added to scene tree."
-msgstr "为 [code]true[/code] 时在添加到场景树时播放音频。"
+msgstr "如果为 [code]true[/code],在添加到场景树时将播放音频。"
#: doc/classes/AudioStreamPlayer.xml doc/classes/AudioStreamPlayer2D.xml
msgid "Bus on which this audio is playing."
@@ -14962,7 +14963,7 @@ msgid ""
"without smoothing, even with this setting enabled, invoke [method "
"reset_smoothing]."
msgstr ""
-"为 [code]true[/code] 时,相机会在达到æžé™æ—¶å¹³æ»‘åœ°åœæ­¢ã€‚\n"
+"如果为 [code]true[/code],相机会在达到æžé™æ—¶å¹³æ»‘åœ°åœæ­¢ã€‚\n"
"当 [member smoothing_enabled] 为 [code]false[/code] 时,该属性无效。\n"
"[b]注æ„:[/b]è¦ç«‹å³å°†ç›¸æœºçš„ä½ç½®æ›´æ–°åˆ°é™åˆ¶èŒƒå›´å†…而ä¸è¿›è¡Œå¹³æ»‘,å³ä½¿å¯ç”¨äº†æ­¤è®¾"
"置,也è¦è°ƒç”¨ [method reset_smoothing]。"
@@ -15003,15 +15004,15 @@ msgstr "相机的过程回调。请å‚阅[enum Camera2DProcessMode]。"
#: doc/classes/Camera2D.xml
msgid "If [code]true[/code], the camera view rotates with the target."
-msgstr "为 [code]true[/code] 时,相机视图将éšç›®æ ‡æ—‹è½¬ã€‚"
+msgstr "如果为 [code]true[/code],相机视图将éšç›®æ ‡æ—‹è½¬ã€‚"
#: doc/classes/Camera2D.xml
msgid ""
"If [code]true[/code], the camera smoothly moves towards the target at "
"[member smoothing_speed]."
msgstr ""
-"为 [code]true[/code] 时,相机将以 [member smoothing_speed] 的速度平滑地æœç›®æ ‡"
-"移动。"
+"如果为 [code]true[/code],相机将以 [member smoothing_speed] 的速度平滑地æœç›®"
+"标移动。"
#: doc/classes/Camera2D.xml
msgid ""
@@ -15045,10 +15046,12 @@ msgid ""
msgstr "相机的ä½ç½®è¦è€ƒè™‘垂直/æ°´å¹³å移和å±å¹•尺寸。"
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr "相机通过 [code]_physics_process[/code] 回调进行更新。"
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr "相机通过 [code]_process[/code] 回调进行更新。"
@@ -16766,11 +16769,11 @@ msgstr ""
#: doc/classes/ClippedCamera.xml
msgid "If [code]true[/code], the camera stops on contact with [Area]s."
-msgstr "为 [code]true[/code] 时,相机将在与 [Area] æŽ¥è§¦æ—¶åœæ­¢ã€‚"
+msgstr "如果为 [code]true[/code],相机将在与 [Area] æŽ¥è§¦æ—¶åœæ­¢ã€‚"
#: doc/classes/ClippedCamera.xml
msgid "If [code]true[/code], the camera stops on contact with [PhysicsBody]s."
-msgstr "为 [code]true[/code] 时,相机将在与 [PhysicsBody] æŽ¥è§¦æ—¶åœæ­¢ã€‚"
+msgstr "如果为 [code]true[/code],相机将在与 [PhysicsBody] æŽ¥è§¦æ—¶åœæ­¢ã€‚"
#: doc/classes/ClippedCamera.xml
msgid ""
@@ -21615,7 +21618,7 @@ msgstr ""
msgid ""
"The [Mesh] used for each particle. If [code]null[/code], particles will be "
"spheres."
-msgstr "æ¯ä¸ªç²’å­ä½¿ç”¨çš„ [Mesh]。如果[code]null[/code],则粒å­å°†æ˜¯çƒå½¢ã€‚"
+msgstr "æ¯ä¸ªç²’å­ä½¿ç”¨çš„ [Mesh]。如果为 [code]null[/code],则粒å­å°†ä¸ºçƒå½¢ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/Particles2D.xml
@@ -21640,7 +21643,7 @@ msgstr ""
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's orbital velocity will vary along this [Curve]."
-msgstr "æ¯ä¸ªç²’å­çš„轨é“速度将沿此 [Curve] å˜åŒ–。"
+msgstr "æ¯ä¸ªç²’å­çš„轨é“速度将跟éšè¿™ä¸ª [Curve] å˜åŒ–。"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -21661,7 +21664,7 @@ msgstr "径å‘加速度应用于æ¯ä¸ªç²’å­ã€‚使粒å­åŠ é€Ÿè¿œç¦»åŽŸç‚¹ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's radial acceleration will vary along this [Curve]."
-msgstr "æ¯ä¸ªç²’å­çš„径å‘加速度将沿此 [Curve] å˜åŒ–。"
+msgstr "æ¯ä¸ªç²’å­çš„径å‘加速度将跟éšè¿™ä¸ª [Curve] å˜åŒ–。"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -21676,31 +21679,31 @@ msgstr "å‘å°„å¯¿å‘½éšæœºçŽ‡ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
msgid "Initial scale applied to each particle."
-msgstr "åˆå§‹æ¯”例应用于æ¯ä¸ªç²’å­ã€‚"
+msgstr "æ¯ä¸ªç²’å­çš„åˆå§‹ç¼©æ”¾ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's scale will vary along this [Curve]."
-msgstr "æ¯ä¸ªç²’å­çš„æ¯”例将éšç€ [Curve] çš„å˜åŒ–而å˜åŒ–。"
+msgstr "æ¯ä¸ªç²’å­çš„缩放将跟éšè¿™ä¸ª [Curve] å˜åŒ–。"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
msgid "Scale randomness ratio."
-msgstr "æ ‡åº¦éšæœºçŽ‡ã€‚"
+msgstr "ç¼©æ”¾éšæœºçŽ‡ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/Particles2D.xml
msgid ""
"Particle system's running speed scaling ratio. A value of [code]0[/code] can "
"be used to pause the particles."
-msgstr "ç²’å­ç³»ç»Ÿçš„è¿è¡Œé€Ÿåº¦ç¼©æ”¾æ¯”例。值[code]0[/code]å¯ç”¨äºŽæš‚åœç²’å­ã€‚"
+msgstr "ç²’å­ç³»ç»Ÿçš„è¿è¡Œé€Ÿåº¦ç¼©æ”¾æ¯”例。将值设为 [code]0[/code] å¯ç”¨äºŽæš‚åœç²’å­ã€‚"
#: doc/classes/CPUParticles.xml
msgid ""
"Each particle's initial direction range from [code]+spread[/code] to [code]-"
"spread[/code] degrees. Applied to X/Z plane and Y/Z planes."
msgstr ""
-"æ¯ä¸ªç²’å­çš„åˆå§‹æ–¹å‘范围为[code]+spread[/code]至[code]-spread[/code]度。适用于"
-"X/Zå¹³é¢å’ŒY/Zå¹³é¢ã€‚"
+"æ¯ä¸ªç²’å­çš„åˆå§‹æ–¹å‘范围为 [code]+spread[/code] 至 [code]-spread[/code] 度。适"
+"用于 X/Z å¹³é¢å’Œ Y/Z å¹³é¢ã€‚"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -21713,7 +21716,7 @@ msgstr ""
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
msgid "Each particle's tangential acceleration will vary along this [Curve]."
-msgstr "æ¯ä¸ªç²’å­çš„切å‘加速度将沿此 [Curve] å˜åŒ–。"
+msgstr "æ¯ä¸ªç²’å­çš„切å‘加速度将跟éšè¿™ä¸ª [Curve] å˜åŒ–。"
#: doc/classes/CPUParticles.xml doc/classes/CPUParticles2D.xml
#: doc/classes/ParticlesMaterial.xml
@@ -21932,23 +21935,23 @@ msgstr "æ¯ä¸ªç²’å­çš„åˆå§‹é¢œè‰²ã€‚如果定义了 [member texture],它将ä
msgid ""
"Each particle's color will vary along this [Gradient] (multiplied with "
"[member color])."
-msgstr "æ¯ä¸ªç²’å­çš„颜色将éšç€è¿™ä¸ª [Gradient] å˜åŒ–,å³ä¸Ž [member color] 相乘。"
+msgstr "æ¯ä¸ªç²’å­çš„颜色将éšç€è¿™ä¸ª [Gradient] å˜åŒ–(与 [member color] 相乘)。"
#: doc/classes/CPUParticles2D.xml
msgid ""
"The rectangle's extents if [member emission_shape] is set to [constant "
"EMISSION_SHAPE_RECTANGLE]."
msgstr ""
-"如果 [member emission_shape] 设置为 [constant EMISSION_SHAPE_RECTANGLE],则矩"
-"形的范围。"
+"[member emission_shape] 设置为 [constant EMISSION_SHAPE_RECTANGLE] 时,该矩形"
+"的范围。"
#: doc/classes/CPUParticles2D.xml
msgid ""
"The sphere's radius if [member emission_shape] is set to [constant "
"EMISSION_SHAPE_SPHERE]."
msgstr ""
-"如果 [member emission_shape] 设置为 [constant EMISSION_SHAPE_SPHERE],则çƒä½“"
-"çš„åŠå¾„。"
+"[member emission_shape] 设置为 [constant EMISSION_SHAPE_SPHERE] 时,该çƒä½“çš„"
+"åŠå¾„。"
#: doc/classes/CPUParticles2D.xml doc/classes/Particles.xml
#: doc/classes/Particles2D.xml
@@ -22070,7 +22073,7 @@ msgstr ""
" key.save(\"user://generated.key\")\n"
" cert.save(\"user://generated.crt\")\n"
" # 加密\n"
-" var data = \"Some data\"\n"
+" var data = \"具体的数æ®\"\n"
" var encrypted = crypto.encrypt(key, data.to_utf8())\n"
" # 解密\n"
" var decrypted = crypto.decrypt(key, encrypted)\n"
@@ -24229,9 +24232,12 @@ msgstr ""
"æ¢çš„ä¸–ç•Œç©ºé—´åæ ‡ï¼ˆåŽŸç‚¹ï¼‰ä¼šè¢«å¿½ç•¥ã€‚åªä¼šç”¨åŸºæ¥ç¡®å®šå…‰çº¿çš„æ–¹å‘。"
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
"远处阴影分裂的é¢å¤–åç½®é‡ã€‚如果自身阴影åªäº§ç”Ÿè¿œå¤„的分裂,增加这个值å¯ä»¥ä¿®å¤å®ƒ"
"们。"
@@ -24239,9 +24245,10 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
-"如果为 [code]true[/code],则会牺牲阴影细节,以æ¢å–更平滑的分割之间的过渡。"
#: doc/classes/DirectionalLight.xml
msgid ""
@@ -24250,8 +24257,12 @@ msgid ""
msgstr "优化阴影渲染的细节与è¿åŠ¨ã€‚è§ [enum ShadowDepthRange]。"
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
-msgstr "阴影分割的最大è·ç¦»ã€‚"
+msgid ""
+"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)."
+msgstr ""
#: doc/classes/DirectionalLight.xml
msgid "The light's shadow rendering algorithm. See [enum ShadowMode]."
@@ -24264,32 +24275,35 @@ msgid ""
msgstr "当物体垂直于光线时,å¯ç”¨äºŽä¿®å¤è‡ªèº«é˜´å½±çš„特殊情况。"
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"相机到影å­åˆ†å‰²1çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]ã€‚åªæœ‰å½“"
"[member directional_shadow_mode]是[code]SHADOW_PARALLEL_2_SPLITS[/code]或"
"[code]SHADOW_PARALLEL_4_SPLITS[/code]æ—¶æ‰ä½¿ç”¨ã€‚"
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"阴影分割1到分割2çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。仅在"
"[member directional_shadow_mode]为[code]SHADOW_PARALLEL_2_SPLITS[/code]或"
"[code]SHADOW_PARALLEL_4_SPLITS[/code]时使用。"
#: doc/classes/DirectionalLight.xml
+#, fuzzy
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
"从影å­åˆ†å‰²2到分割3çš„è·ç¦»ã€‚相对于[member directional_shadow_max_distance]。åª"
"有当[member directional_shadow_mode]为[code]SHADOW_PARALLEL_4_SPLITS[/code]时"
@@ -24905,9 +24919,9 @@ msgid ""
"control whose size changes over time, unless a pixel art aesthetic is "
"desired."
msgstr ""
-"为 [code]true[/code] 时将使用过滤功能。如果字体过度采样被ç¦ç”¨æˆ–无效,这将使字"
-"体在缩放时å˜å¾—模糊,而éžåƒç´ åŒ–ã€‚å½“åœ¨å°ºå¯¸éšæ—¶å˜åŒ–的控件中使用字体时,建议å¯ç”¨"
-"è¿™ä¸ªåŠŸèƒ½ï¼Œé™¤éžæ˜¯åƒç´ è®¾è®¡ã€‚"
+"如果为 [code]true[/code],将使用过滤功能。如果字体过度采样被ç¦ç”¨æˆ–无效,这将"
+"使字体在缩放时å˜å¾—模糊,而éžåƒç´ åŒ–ã€‚å½“åœ¨å°ºå¯¸éšæ—¶å˜åŒ–的控件中使用字体时,建议"
+"å¯ç”¨è¿™ä¸ªåŠŸèƒ½ï¼Œé™¤éžæ˜¯åƒç´ è®¾è®¡ã€‚"
#: doc/classes/DynamicFont.xml
msgid ""
@@ -24915,8 +24929,8 @@ msgid ""
"appearance when downscaling it if font oversampling is disabled or "
"ineffective."
msgstr ""
-"为 [code]true[/code] 时将使用 mipmap 多级æ¸è¿œçº¹ç†ã€‚在字体过度采样被ç¦ç”¨æˆ–无效"
-"æ—¶ï¼Œå¯æ”¹å–„å­—ä½“ç¼©å°æ—¶çš„表现。"
+"如果为 [code]true[/code],将使用 mipmap 多级æ¸è¿œçº¹ç†ã€‚在字体过度采样被ç¦ç”¨æˆ–"
+"æ— æ•ˆæ—¶ï¼Œå¯æ”¹å–„å­—ä½“ç¼©å°æ—¶çš„表现。"
#: doc/classes/DynamicFont.xml
msgid "Spacing at the top."
@@ -24950,8 +24964,8 @@ msgid ""
"If [code]true[/code], the font is rendered with anti-aliasing. This property "
"applies both to the main font and its outline (if it has one)."
msgstr ""
-"为 [code]true[/code] æ—¶å°†ä»¥æŠ—é”¯é½¿æ–¹å¼æ¸²æŸ“该字体。此属性既适用于主字体,也适用"
-"于其轮廓(如果有)。"
+"如果为 [code]true[/code]ï¼Œå°†ä»¥æŠ—é”¯é½¿æ–¹å¼æ¸²æŸ“该字体。此属性既适用于主字体,也"
+"适用于其轮廓(如果有)。"
#: doc/classes/DynamicFontData.xml
msgid "The path to the vector font file."
@@ -26310,8 +26324,8 @@ msgid ""
"If [code]true[/code], enables distraction-free mode which hides side docks "
"to increase the space available for the main view."
msgstr ""
-"为 [code]true[/code] æ—¶å°†å¯ç”¨ä¸“注模å¼ï¼Œè¯¥æ¨¡å¼ä¼šéšè—ä¾§è¾¹é¢æ¿ï¼Œå¢žåŠ ä¸»è§†å›¾çš„å¯ç”¨"
-"空间。"
+"如果为 [code]true[/code],将å¯ç”¨ä¸“注模å¼ï¼Œè¯¥æ¨¡å¼ä¼šéšè—ä¾§è¾¹é¢æ¿ï¼Œå¢žåŠ ä¸»è§†å›¾çš„"
+"å¯ç”¨ç©ºé—´ã€‚"
#: doc/classes/EditorPlugin.xml
msgid "Used by the editor to extend its functionality."
@@ -26325,7 +26339,7 @@ msgid ""
"editor."
msgstr ""
"编辑器使用æ’ä»¶æ¥æ‰©å±•功能。最常è§çš„æ’ä»¶ç±»åž‹æ˜¯ç¼–è¾‘ç»™å®šçš„èŠ‚ç‚¹æˆ–èµ„æºç±»åž‹ã€å¯¼å…¥æ’"
-"件和导出æ’件。å¦è¯·å‚阅[EditorScript]å‘编辑器添加函数。"
+"件和导出æ’件。å¦è¯·å‚阅 [EditorScript] å‘编辑器添加函数。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26344,7 +26358,7 @@ msgstr ""
"å°†æŽ§ä»¶æ·»åŠ åˆ°åº•éƒ¨é¢æ¿ï¼ˆåŒ…å«â€œè¾“出â€â€œè°ƒè¯•â€â€œåŠ¨ç”»â€ç­‰ï¼‰ã€‚返回对添加的按钮的引用。您"
"å¯ä»¥æ ¹æ®éœ€è¦éšè—/显示按钮。åœç”¨æ’ä»¶åŽï¼Œè¯·ç¡®ä¿ä½¿ç”¨ [method "
"remove_control_from_bottom_panel] 移除自定义控件,并使用 [method Node."
-"queue_free] 释放。"
+"queue_free] 将其释放。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26357,11 +26371,11 @@ msgid ""
"with [method remove_control_from_container] and free it with [method Node."
"queue_free]."
msgstr ""
-"将自定义控件添加到容器中(å‚阅 [enum CustomControlContainer])。在编辑器用户"
-"界é¢ä¸­ï¼Œæœ‰è®¸å¤šä½ç½®å¯ä»¥æ·»åŠ è‡ªå®šä¹‰æŽ§ä»¶ã€‚\n"
+"å°†è‡ªå®šä¹‰æŽ§ä»¶æ·»åŠ åˆ°å®¹å™¨ä¸­ï¼ˆè§ [enum CustomControlContainer])。在编辑器用户界"
+"é¢ä¸­ï¼Œæœ‰è®¸å¤šä½ç½®å¯ä»¥æ·»åŠ è‡ªå®šä¹‰æŽ§ä»¶ã€‚\n"
"请记ä½ï¼Œæ‚¨å¿…é¡»è‡ªå·±ç®¡ç†æ‚¨çš„自定义控件的å¯è§æ€§ï¼ˆå¹¶ä¸”很å¯èƒ½åœ¨æ·»åŠ åŽéšè—它)。\n"
-"当你的æ’ä»¶åœç”¨æ—¶ï¼Œè¯·ç¡®ä¿ä½¿ç”¨ [method remove_control_from_container] 删除你的"
-"自定义控件,并使用 [method Node.queue_free] 释放它。"
+"当你的æ’件被åœç”¨æ—¶ï¼Œè¯·ç¡®ä¿ä½¿ç”¨ [method remove_control_from_container] 删除你"
+"的自定义控件,并使用 [method Node.queue_free] 将其释放。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26535,7 +26549,7 @@ msgstr ""
msgid ""
"Called by the engine when the user disables the [EditorPlugin] in the Plugin "
"tab of the project settings window."
-msgstr "当用户在项目设置窗å£çš„æ’ä»¶é€‰é¡¹å¡ä¸­ç¦ç”¨[EditorPlugin]时,由引擎调用。"
+msgstr "当用户在项目设置窗å£çš„æ’ä»¶é€‰é¡¹å¡ä¸­ç¦ç”¨ [EditorPlugin] 时,由引擎调用。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -26569,8 +26583,8 @@ msgid ""
" return false\n"
"[/codeblock]"
msgstr ""
-"当2D编辑器的视窗被更新时,由引擎调用。使用 [code]overlay[/code] [Control] 进"
-"行绘制。你å¯ä»¥é€šè¿‡è°ƒç”¨ [method update_overlays] 手动更新视窗。\n"
+"引擎会在 2D 编辑器的视区å‘生更新时调用。使用 [code]overlay[/code] [Control] "
+"进行绘制。你å¯ä»¥é€šè¿‡è°ƒç”¨ [method update_overlays] 手动更新视窗。\n"
"[codeblock]\n"
"func forward_canvas_draw_over_viewport(overlay):\n"
" # 在光标ä½ç½®ç”»ä¸€ä¸ªåœ†ã€‚\n"
@@ -26661,7 +26675,7 @@ msgid ""
" return false\n"
"[/codeblock]"
msgstr ""
-"当3D编辑器的视窗被更新时,由引擎调用。使用 [code]overlay[/code] 控件 "
+"引擎会在 3D 编辑器的视区å‘生更新时调用。使用 [code]overlay[/code] 控件 "
"[Control] 进行绘制。你å¯ä»¥é€šè¿‡è°ƒç”¨ [method update_overlays] 更新覆盖手动更新"
"视窗。\n"
"[codeblock]\n"
@@ -26993,9 +27007,9 @@ msgid ""
"inside [method forward_spatial_gui_input]. It might be especially usable if "
"your plugin will want to use raycast in the scene."
msgstr ""
-"如果你想在[method forward_spatial_gui_input]é‡Œé¢æŽ¥æ”¶æ¥è‡ª3D视图å±å¹•的输入,请"
-"使用这个方法。如果你的æ’件想è¦åœ¨åœºæ™¯ä¸­ä½¿ç”¨å…‰çº¿å¹¿æ’­ï¼Œé‚£ä¹ˆè¿™ä¸ªæ–¹æ³•å¯èƒ½ç‰¹åˆ«æœ‰"
-"用。"
+"如果你想在 [method forward_spatial_gui_input] é‡Œé¢æŽ¥æ”¶æ¥è‡ª 3D 视图å±å¹•的输"
+"入,请使用这个方法。如果你的æ’件想è¦åœ¨åœºæ™¯ä¸­ä½¿ç”¨å…‰çº¿æŠ•射,那么这个方法å¯èƒ½ç‰¹"
+"别有用。"
#: doc/classes/EditorPlugin.xml
msgid ""
@@ -28874,7 +28888,7 @@ msgid ""
"the editor and when running the project from the editor, but it will "
"evaluate to [code]false[/code] when the code is run from an exported project."
msgstr ""
-"为 [code]true[/code] æ—¶è¡¨ç¤ºè¯¥è„šæœ¬ç›®å‰æ­£åœ¨ç¼–辑器内è¿è¡Œã€‚这对 [code]tool[/"
+"如果为 [code]true[/code]ï¼Œè¡¨ç¤ºè¯¥è„šæœ¬ç›®å‰æ­£åœ¨ç¼–辑器内è¿è¡Œã€‚这对 [code]tool[/"
"code] 脚本很有用,å¯ä»¥åœ¨ç‰¹å®šæ¡ä»¶ä¸‹ç»˜åˆ¶ç¼–辑器辅助内容,或者防止在编辑器中æ„外"
"地è¿è¡Œä¼šå½±å“场景状æ€çš„“游æˆâ€ä»£ç ã€‚\n"
"[codeblock]\n"
@@ -37613,6 +37627,7 @@ msgid "Controls the mouse mode. See [enum MouseMode] for more information."
msgstr "控制鼠标模å¼ã€‚详情请å‚阅 [enum MouseMode]。"
#: doc/classes/Input.xml
+#, fuzzy
msgid ""
"If [code]true[/code], similar input events sent by the operating system are "
"accumulated. When input accumulation is enabled, all input events generated "
@@ -37623,7 +37638,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
"如果为 [code]true[/code],会对æ“作系统å‘é€çš„类似输入事件进行累积。当å¯ç”¨è¾“å…¥"
"累积时,在一帧中产生的所有输入事件将被åˆå¹¶ï¼Œå¹¶åœ¨è¯¥å¸§å®Œæˆæ¸²æŸ“æ—¶å‘出。因此,这"
@@ -38355,13 +38373,15 @@ msgid "Input event type for mouse motion events."
msgstr "鼠标移动事件的输入事件类型。"
#: doc/classes/InputEventMouseMotion.xml
+#, fuzzy
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -38763,6 +38783,12 @@ msgid ""
msgstr "如果为 [code]true[/code],并且设置了目标,相机将自动移动。"
#: doc/classes/InterpolatedCamera.xml
+#, fuzzy
+msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr "相机的过程回调。请å‚阅[enum Camera2DProcessMode]。"
+
+#: doc/classes/InterpolatedCamera.xml
msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
@@ -45389,7 +45415,7 @@ msgstr ""
"å…许代ç†åç¦»ç†æƒ³è·¯å¾„的最大è·ç¦»ã€‚å¯èƒ½ä¸ºäº†é˜²æ’žè€Œäº§ç”Ÿå离。超出最大è·ç¦»æ—¶ï¼Œä¼šé‡"
"æ–°è®¡ç®—ç†æƒ³è·¯å¾„。"
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -45522,6 +45548,14 @@ msgstr ""
"ä½åŸŸï¼Œç”¨äºŽå†³å®šè¯¥ [NavigationAgent2D] 所属的导航地图层。请求路径时,代ç†ä¼šå¿½ç•¥"
"没有任何匹é…层的导航网格。"
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr "ç”¨äºŽæ¨¡æ‹Ÿå¯æ­¥è¡ŒåŒºåŸŸå’Œéšœç¢ç‰©çš„网格。"
@@ -51787,8 +51821,8 @@ msgid ""
"Shows all resources in the game. Optionally, the list can be written to a "
"file by specifying a file path in [code]tofile[/code]."
msgstr ""
-"显示游æˆä¸­çš„æ‰€æœ‰èµ„æºã€‚也å¯ä»¥é€šè¿‡åœ¨[code]tofile[/code]中指定文件路径将该列表写"
-"入文件。"
+"显示游æˆä¸­çš„æ‰€æœ‰èµ„æºã€‚也å¯ä»¥é€šè¿‡åœ¨ [code]tofile[/code] 中指定文件路径将该列表"
+"写入文件。"
#: doc/classes/OS.xml
msgid "Shows the list of loaded textures sorted by size in memory."
@@ -51808,16 +51842,17 @@ msgid ""
"Windows or bounce the dock icon on OSX.\n"
"[b]Note:[/b] This method is implemented on Linux, macOS and Windows."
msgstr ""
-"è¦æ±‚用户注æ„该窗å£ã€‚它会在Windows上闪çƒä»»åŠ¡æ æŒ‰é’®ï¼Œæˆ–在OSX上弹出Dock图标。\n"
-"[b]注æ„:[/b]这个方法在Linuxã€macOSå’ŒWindows上实现。"
+"è¦æ±‚用户注æ„该窗å£ã€‚它会在 Windows 上闪çƒä»»åŠ¡æ æŒ‰é’®ï¼Œæˆ–在 OSX 上让 Dock 图标"
+"弹跳。\n"
+"[b]注æ„:[/b]这个方法在 Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
"At the moment this function is only used by [code]AudioDriverOpenSL[/code] "
"to request permission for [code]RECORD_AUDIO[/code] on Android."
msgstr ""
-"ç›®å‰ï¼Œè¿™ä¸ªå‡½æ•°åªè¢«[code]AudioDriverOpenSL[/code]用æ¥è¯·æ±‚Android上"
-"[code]RECORD_AUDIO[/code]çš„æƒé™ã€‚"
+"ç›®å‰ï¼Œè¿™ä¸ªå‡½æ•°åªè¢« [code]AudioDriverOpenSL[/code] 用æ¥è¯·æ±‚ Android 上 "
+"[code]RECORD_AUDIO[/code] çš„æƒé™ã€‚"
#: doc/classes/OS.xml
msgid ""
@@ -51826,9 +51861,9 @@ msgid ""
"applications.\n"
"[b]Note:[/b] This method is implemented on Android."
msgstr ""
-"通过这个功能,你å¯ä»¥ç”³è¯·å±é™©çš„æƒé™ï¼Œå› ä¸ºåœ¨Android应用程åºä¸­ï¼Œæ­£å¸¸çš„æƒé™ä¼šåœ¨å®‰"
+"ä½ å¯ä»¥é€šè¿‡è¿™ä¸ªå‡½æ•°ç”³è¯·å±é™©çš„æƒé™ï¼Œå› ä¸ºåœ¨ Android 应用程åºä¸­ï¼Œæ­£å¸¸çš„æƒé™ä¼šåœ¨å®‰"
"装时自动授予。\n"
-"[b]注æ„:[/b]此方法在Android上实现。"
+"[b]注æ„:[/b]这个方法在 Android 上实现。"
#: doc/classes/OS.xml
msgid ""
@@ -51875,15 +51910,15 @@ msgstr ""
"应用程åºå¯ä»¥é€šè¿‡ä½¿ç”¨ [method get_ime_selection] å’Œ [method get_ime_text] 函数"
"æ¥æ£€ç´¢ç»„åˆçжæ€ã€‚\n"
"è¾“å…¥å®Œæˆæ—¶æäº¤å®Œæˆçš„组åˆå­—符串。\n"
-"[b]注æ„:[/b]该方法在 Linuxã€macOS å’Œ Windows 上实现。"
+"[b]注æ„:[/b]这个方法在 Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
"Sets position of IME suggestion list popup (in window coordinates).\n"
"[b]Note:[/b] This method is implemented on Linux, macOS and Windows."
msgstr ""
-"设置 IME 建议列表弹出窗å£çš„ä½ç½®ï¼ˆåœ¨çª—å£å标中)。\n"
-"[b]注æ„:[/b]此方法在 Linuxã€macOS å’Œ Windows 上实现。"
+"设置 IME 建议列表弹出窗å£çš„ä½ç½®ï¼ˆä½¿ç”¨çª—å£å标)。\n"
+"[b]注æ„:[/b]这个方法在 Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
@@ -51896,7 +51931,7 @@ msgstr ""
"使用多尺寸平å°ç‰¹å®šå›¾æ ‡æ–‡ä»¶è®¾ç½®æ¸¸æˆçš„图标(在 Windows 上是 [code]*.ico[/"
"code],在 macOS 上是 [code]*.icns[/code])。\n"
"适当的大å°å­å›¾æ ‡ç”¨äºŽçª—壿 ‡é¢˜ã€ä»»åŠ¡æ /程åºåžå’Œçª—å£é€‰æ‹©å¯¹è¯æ¡†ã€‚\n"
-"[b]注æ„:[/b]此方法在 macOS å’Œ Windows 上实现。"
+"[b]注æ„:[/b]这个方法在 macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid "Sets the name of the current thread."
@@ -51904,7 +51939,7 @@ msgstr "设置当å‰çº¿ç¨‹çš„å称。"
#: doc/classes/OS.xml
msgid "Enables backup saves if [code]enabled[/code] is [code]true[/code]."
-msgstr "如果[code]enabled[/code]为 [code]true[/code],则å¯ç”¨å¤‡ä»½ä¿å­˜ã€‚"
+msgstr "如果 [code]enabled[/code] 为 [code]true[/code],则å¯ç”¨å¤‡ä»½ä¿å­˜ã€‚"
#: doc/classes/OS.xml
msgid ""
@@ -51912,7 +51947,7 @@ msgid ""
"[b]Note:[/b] This method is implemented on Linux, macOS and Windows."
msgstr ""
"è®¾ç½®çª—å£æ˜¯å¦åº”始终ä½äºŽé¡¶éƒ¨ã€‚\n"
-"[b]注æ„:[/b]该方法在 Linuxã€macOS å’Œ Windows 上实现。"
+"[b]注æ„:[/b]这个方法在 Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
@@ -51937,18 +51972,18 @@ msgstr ""
"设置窗å£çš„一个接å—鼠标事件的多边形区域。该区域外的鼠标事件将被传递出去。\n"
"传递一个空数组将ç¦ç”¨ç©¿é€æ”¯æŒï¼ˆæ‰€æœ‰é¼ æ ‡äº‹ä»¶å°†è¢«çª—壿‹¦æˆªï¼Œè¿™æ˜¯é»˜è®¤è¡Œä¸ºï¼‰ã€‚\n"
"[codeblock]\n"
-"# 设置区域,使用Path2D节点。\n"
-"OS.set_window_mouse_passthrough($Path2D.curve.get_baked_points() )\n"
+"# 设置区域,使用 Path2D 节点。\n"
+"OS.set_window_mouse_passthrough($Path2D.curve.get_baked_points())\n"
"\n"
-"# 设置区域,使用Polygon2D节点。\n"
+"# 设置区域,使用 Polygon2D 节点。\n"
"OS.set_window_mouse_passthrough($Polygon2D.polygon)\n"
"\n"
"# é‡ç½®åŒºåŸŸä¸ºé»˜è®¤å€¼ã€‚\n"
-"OS.set_window_mouse_passthrough([] )\n"
+"OS.set_window_mouse_passthrough([])\n"
"[/codeblock]\n"
-"[b]注æ„:[/b]在Windows上,ä½äºŽåŒºåŸŸå¤–的窗å£éƒ¨åˆ†ä¸ä¼šè¢«ç»˜åˆ¶ï¼Œè€Œåœ¨Linuxå’ŒmacOS上"
-"则会。\n"
-"[b]注æ„:[/b]这个方法在Linuxã€macOSå’ŒWindows上实现。"
+"[b]注æ„:[/b]在 Windows 上,ä½äºŽåŒºåŸŸå¤–的窗å£éƒ¨åˆ†ä¸ä¼šè¢«ç»˜åˆ¶ï¼Œè€Œåœ¨ Linux å’Œ "
+"macOS 上则会。\n"
+"[b]注æ„:[/b]这个方法在 Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
@@ -51960,7 +51995,7 @@ msgstr ""
"å°†çª—å£æ ‡é¢˜è®¾ç½®ä¸ºæŒ‡å®šçš„字符串。\n"
"[b]注æ„:[/b]应该å¶å°”使用,ä¸è¦æ¯å¸§éƒ½è®¾ç½®ï¼Œå› ä¸ºè¿™ä¼šå¯¹æŸäº›çª—å£ç®¡ç†å™¨çš„æ€§èƒ½äº§ç”Ÿ"
"è´Ÿé¢å½±å“。\n"
-"[b]注æ„:[/b]该方法在 HTML5ã€Linuxã€macOS å’Œ Windows 上实现。"
+"[b]注æ„:[/b]这个方法在 HTML5ã€Linuxã€macOS å’Œ Windows 上实现。"
#: doc/classes/OS.xml
msgid ""
@@ -51991,7 +52026,7 @@ msgstr ""
"[code]mailto[/code] URL 方案[/url]。\n"
"å¯ä»¥ä½¿ç”¨ [method ProjectSettings.globalize_path] å°† [code]res://[/code] å’Œ "
"[code]user://[/code] 路径转æ¢ä¸ºæœ¬æ–¹æ³•所使用的系统路径。\n"
-"[b]注æ„:[/b]本方法在 Androidã€iOSã€HTML5ã€Linuxã€macOSã€ä»¥åŠ Windows 上实"
+"[b]注æ„:[/b]这个方法在 Androidã€iOSã€HTML5ã€Linuxã€macOSã€ä»¥åŠ Windows 上实"
"现。"
#: doc/classes/OS.xml
@@ -52011,7 +52046,7 @@ msgstr ""
"测)。\n"
"éœ€è¦æŠŠ [code]multiline[/code] 傿•°è®¾ç½®ä¸º [code]true[/code] æ‰èƒ½è¾“入多行文本,"
"如在 [TextEdit] 中。\n"
-"[b]注æ„:[/b]此方法在 Androidã€iOS å’Œ UWP 上实现。"
+"[b]注æ„:[/b]这个方法在 Androidã€iOS å’Œ UWP 上实现。"
#: doc/classes/OS.xml
msgid "The clipboard from the host OS. Might be unavailable on some platforms."
@@ -52330,27 +52365,27 @@ msgstr ""
#: doc/classes/OS.xml
msgid "Landscape screen orientation."
-msgstr "横å‘å±å¹•æ–¹å‘。"
+msgstr "æ¨ªå±æ–¹å‘。"
#: doc/classes/OS.xml
msgid "Portrait screen orientation."
-msgstr "纵å‘å±å¹•æ–¹å‘。"
+msgstr "ç«–å±æ–¹å‘。"
#: doc/classes/OS.xml
msgid "Reverse landscape screen orientation."
-msgstr "å转横å‘å±å¹•æ–¹å‘。"
+msgstr "å€’æ¨ªå±æ–¹å‘。"
#: doc/classes/OS.xml
msgid "Reverse portrait screen orientation."
-msgstr "å转纵å‘å±å¹•æ–¹å‘。"
+msgstr "å€’ç«–å±æ–¹å‘。"
#: doc/classes/OS.xml
msgid "Uses landscape or reverse landscape based on the hardware sensor."
-msgstr "æ ¹æ®ç¡¬ä»¶ä¼ æ„Ÿå™¨ä½¿ç”¨æ¨ªå‘或å呿¨ªå‘。"
+msgstr "æ ¹æ®ç¡¬ä»¶ä¼ æ„Ÿå™¨ä½¿ç”¨æ¨ªå±æˆ–å€’æ¨ªå±æ–¹å‘。"
#: doc/classes/OS.xml
msgid "Uses portrait or reverse portrait based on the hardware sensor."
-msgstr "æ ¹æ®ç¡¬ä»¶ä¼ æ„Ÿå™¨ä½¿ç”¨çºµå‘或åå‘纵å‘。"
+msgstr "æ ¹æ®ç¡¬ä»¶ä¼ æ„Ÿå™¨ä½¿ç”¨ç«–屿ˆ–倒竖å±ã€‚"
#: doc/classes/OS.xml
msgid "Uses most suitable orientation based on the hardware sensor."
@@ -52542,7 +52577,7 @@ msgstr ""
#: doc/classes/PackedScene.xml
msgid "If passed to [method instance], blocks edits to the scene state."
-msgstr "如果传递给[method instance],则阻止对场景状æ€çš„编辑。"
+msgstr "如果传递给 [method instance],则阻止对场景状æ€çš„编辑。"
#: doc/classes/PackedScene.xml
msgid ""
@@ -52561,7 +52596,7 @@ msgid ""
msgstr ""
"如果传递给 [method instance]ï¼Œå‘æœ¬åœ°åœºæ™¯æä¾›æœ¬åœ°åœºæ™¯èµ„æºã€‚åªæœ‰ä¸»åœºæ™¯åº”该接收"
"主编辑状æ€ã€‚\n"
-"[b]注æ„:[/b]åªåœ¨ç¼–辑器构建中å¯ç”¨ã€‚"
+"[b]注æ„:[/b]仅在编辑器构建中å¯ç”¨ã€‚"
#: doc/classes/PackedScene.xml
msgid ""
@@ -52653,10 +52688,10 @@ msgid ""
"Do not use this option if the serialized object comes from untrusted sources "
"to avoid potential security threats such as remote code execution."
msgstr ""
-"[i]已废弃。[/i] 你应该使用 [code]get_var[/code] å’Œ [code]put_var[/code] 傿•°"
-"æ¥ä»£æ›¿å®ƒã€‚\n"
-"如果为 [code]true[/code],多人游æˆAPIå°†å…许在RPC/RSETs期间对对象进行编ç å’Œè§£"
-"ç ã€‚\n"
+"[i]已废弃。[/i]你应该使用 [code]get_var[/code] å’Œ [code]put_var[/code] 傿•°æ¥"
+"代替它。\n"
+"如果为 [code]true[/code]ï¼Œå¤šäººæ¸¸æˆ API å°†å…许在 RPC/RSET 期间对对象进行编ç å’Œ"
+"è§£ç ã€‚\n"
"[b]警告:[/b]ååºåˆ—化的对象å¯èƒ½åŒ…å«ä¼šè¢«æ‰§è¡Œçš„代ç ã€‚如果åºåˆ—化的对象æ¥è‡ªä¸å—ä¿¡"
"ä»»çš„æ¥æºï¼Œè¯·ä¸è¦ä½¿ç”¨è¿™ä¸ªé€‰é¡¹ï¼Œä»¥é¿å…潜在的安全å¨èƒï¼Œå¦‚è¿œç¨‹ä»£ç æ‰§è¡Œã€‚"
@@ -52739,17 +52774,17 @@ msgstr "è¡¨ç¤ºå½“å‰æ­£åœ¨ä¸Žè¿œç¨‹å¯¹ç­‰æ–¹è¿›è¡Œæ¡æ‰‹çš„ [PacketPeerDTLS] çš„
#: doc/classes/PacketPeerDTLS.xml
msgid ""
"A status representing a [PacketPeerDTLS] that is connected to a remote peer."
-msgstr "表示连接到远程对等方的[PacketPeerDTLS]的状æ€ã€‚"
+msgstr "表示连接到远程对等方的 [PacketPeerDTLS] 的状æ€ã€‚"
#: doc/classes/PacketPeerDTLS.xml
msgid "A status representing a [PacketPeerDTLS] in a generic error state."
-msgstr "表示处于一般错误状æ€çš„[PacketPeerDTLS]的状æ€ã€‚"
+msgstr "表示处于一般错误状æ€çš„ [PacketPeerDTLS] 的状æ€ã€‚"
#: doc/classes/PacketPeerDTLS.xml
msgid ""
"An error status that shows a mismatch in the DTLS certificate domain "
"presented by the host and the domain requested for validation."
-msgstr "显示主机æä¾›çš„DTLSè¯ä¹¦åŸŸä¸Žè¯·æ±‚验è¯çš„域ä¸åŒ¹é…的错误状æ€ã€‚"
+msgstr "显示主机æä¾›çš„ DTLS è¯ä¹¦åŸŸä¸Žè¯·æ±‚验è¯çš„域ä¸åŒ¹é…的错误状æ€ã€‚"
#: doc/classes/PacketPeerStream.xml
msgid "Wrapper to use a PacketPeer over a StreamPeer."
@@ -52768,16 +52803,16 @@ msgstr ""
#: doc/classes/PacketPeerStream.xml
msgid "The wrapped [StreamPeer] object."
-msgstr "被·包装的[StreamPeer]对象。"
+msgstr "被包装的 [StreamPeer] 对象。"
#: doc/classes/PacketPeerUDP.xml
msgid "UDP packet peer."
-msgstr "UDPæ•°æ®åŒ…客户端。"
+msgstr "UDP æ•°æ®åŒ…客户端。"
#: doc/classes/PacketPeerUDP.xml
msgid ""
"UDP packet peer. Can be used to send raw UDP packets as well as [Variant]s."
-msgstr "UDPæ•°æ®åŒ…对等体。å¯ä»¥ç”¨æ¥å‘é€åŽŸå§‹çš„UDPæ•°æ®åŒ…以åŠ[Variant]。"
+msgstr "UDP æ•°æ®åŒ…对等体。å¯ä»¥ç”¨æ¥å‘é€åŽŸå§‹çš„ UDP æ•°æ®åŒ…ä»¥åŠ [Variant]。"
#: doc/classes/PacketPeerUDP.xml
msgid "Closes the UDP socket the [PacketPeerUDP] is currently listening on."
@@ -52905,9 +52940,9 @@ msgid ""
"[b]Note:[/b] [method set_broadcast_enabled] must be enabled before sending "
"packets to a broadcast address (e.g. [code]255.255.255.255[/code])."
msgstr ""
-"设置å‘逿•°æ®åŒ…å’Œå˜é‡çš„目标地å€å’Œç«¯å£ã€‚如果需è¦ï¼Œå°†ä½¿ç”¨DNSè§£æžä¸€ä¸ªä¸»æœºå。\n"
+"设置å‘逿•°æ®åŒ…å’Œå˜é‡çš„目标地å€å’Œç«¯å£ã€‚如果需è¦ï¼Œå°†ä½¿ç”¨ DNS è§£æžä¸»æœºå。\n"
"[b]注æ„:[/b]在å‘广播地å€ï¼ˆä¾‹å¦‚:[code]255.255.255.255[/code])å‘逿•°æ®åŒ…之"
-"å‰ï¼Œå¿…é¡»å¯ç”¨[method set_broadcast_enabled]。"
+"å‰ï¼Œå¿…é¡»å¯ç”¨ [method set_broadcast_enabled]。"
#: doc/classes/PacketPeerUDP.xml
msgid ""
@@ -53047,8 +53082,8 @@ msgid ""
"limit, the background will stop scrolling. Must be lower than [member "
"scroll_limit_end] to work."
msgstr ""
-"开始滚动的左上角é™åˆ¶ã€‚如果相机超出这个é™åˆ¶ï¼ŒèƒŒæ™¯å°†åœæ­¢æ»šåŠ¨ã€‚å¿…é¡»ä½ŽäºŽ[member "
-"scroll_limit_end]æ‰èƒ½å·¥ä½œã€‚"
+"开始滚动的左上角é™åˆ¶ã€‚如果相机超出这个é™åˆ¶ï¼ŒèƒŒæ™¯å°†åœæ­¢æ»šåŠ¨ã€‚å¿…é¡»ä½ŽäºŽ [member "
+"scroll_limit_end] æ‰èƒ½å·¥ä½œã€‚"
#: doc/classes/ParallaxBackground.xml
msgid ""
@@ -53056,8 +53091,8 @@ msgid ""
"limit, the background will stop scrolling. Must be higher than [member "
"scroll_limit_begin] to work."
msgstr ""
-"å³ä¸‹è§’é™åˆ¶æ»šåŠ¨ç»“æŸã€‚如果相机超出这个é™åˆ¶ï¼ŒèƒŒæ™¯å°†åœæ­¢æ»šåŠ¨ã€‚å¿…é¡»é«˜äºŽ[member "
-"scroll_limit_begin]æ‰èƒ½å·¥ä½œã€‚"
+"å³ä¸‹è§’é™åˆ¶æ»šåŠ¨ç»“æŸã€‚如果相机超出这个é™åˆ¶ï¼ŒèƒŒæ™¯å°†åœæ­¢æ»šåŠ¨ã€‚å¿…é¡»é«˜äºŽ [member "
+"scroll_limit_begin] æ‰èƒ½å·¥ä½œã€‚"
#: doc/classes/ParallaxBackground.xml
msgid ""
@@ -53065,8 +53100,8 @@ msgid ""
"[Camera2D], but can be used to manually manage scrolling when no camera is "
"present."
msgstr ""
-"视差背景的滚动值。使用[Camera2D]时自动计算,但å¯ç”¨äºŽæ‰‹åŠ¨ç®¡ç†æ— æ‘„åƒå¤´æ—¶çš„æ»š"
-"动。"
+"视差背景的滚动值。使用 [Camera2D] 时会自动计算,但也å¯ç”¨äºŽæ‰‹åŠ¨ç®¡ç†æ— æ‘„åƒæœºæ—¶"
+"的滚动。"
#: doc/classes/ParallaxLayer.xml
msgid "A parallax scrolling layer to be used with [ParallaxBackground]."
@@ -53092,15 +53127,15 @@ msgid ""
"scrolling background. If an axis is set to [code]0[/code], the [Texture] "
"will not be mirrored."
msgstr ""
-"视差图层的[Texture]镜åƒã€‚ç”¨äºŽåˆ›å»ºæ— é™æ»šåŠ¨çš„èƒŒæ™¯ã€‚å¦‚æžœä¸€ä¸ªè½´è¢«è®¾ç½®ä¸º[code]0[/"
-"code],[Texture]å°†ä¸ä¼šè¢«é•œåƒã€‚"
+"视差图层的 [Texture] 镜åƒã€‚ç”¨äºŽåˆ›å»ºæ— é™æ»šåŠ¨çš„èƒŒæ™¯ã€‚å¦‚æžœæŸä¸ªè½´è¢«è®¾ç½®ä¸º "
+"[code]0[/code],[Texture] å°†ä¸ä¼šè¢«é•œåƒã€‚"
#: doc/classes/ParallaxLayer.xml
msgid ""
"The ParallaxLayer's offset relative to the parent ParallaxBackground's "
"[member ParallaxBackground.scroll_offset]."
msgstr ""
-"ParallaxLayer 相对于父 ParallaxBackground çš„åç§»é‡ [member "
+"该 ParallaxLayer çš„åç§»é‡ï¼Œç›¸å¯¹äºŽçˆ¶ ParallaxBackground çš„ [member "
"ParallaxBackground.scroll_offset]。"
#: doc/classes/ParallaxLayer.xml
@@ -62852,10 +62887,13 @@ msgid ""
msgstr "阴影贴图的细分象é™å¤§å°ã€‚请å‚阅阴影映射文档。"
#: doc/classes/ProjectSettings.xml
+#, fuzzy
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
-msgstr "阴影图集的尺寸(用于 OmniLight å’Œ SpotLightï¼‰ã€‚è§æ–‡æ¡£ã€‚"
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
+msgstr ""
+"设置阴影图集的图åƒå¤§å°ï¼ˆç”¨äºŽå…¨å‘光和èšå…‰ï¼‰ã€‚该值将被四èˆäº”入到最接近的 2 çš„"
+"幂。"
#: doc/classes/ProjectSettings.xml
msgid ""
@@ -64068,8 +64106,8 @@ msgid ""
"queries are required between physics frames (or during the same frame) use "
"[method force_raycast_update] after adjusting the raycast."
msgstr ""
-"RayCast 表示一æ¡ä»ŽåŽŸç‚¹åˆ°ç›®æ ‡ä½ç½® [code]cast_to[/code] çš„ç›´çº¿ã€‚å®ƒè¢«ç”¨æ¥æŸ¥è¯¢2D"
-"空间,以便沿ç€å°„线的路径找到最近的物体。\n"
+"RayCast 表示一æ¡ä»ŽåŽŸç‚¹åˆ°ç›®æ ‡ä½ç½® [code]cast_to[/code] çš„ç›´çº¿ã€‚å®ƒè¢«ç”¨æ¥æŸ¥è¯¢ "
+"2D 空间,以便沿ç€å°„线的路径找到最近的物体。\n"
"RayCast2D å¯ä»¥å¿½ç•¥ä¸€äº›ç‰©ä½“,通过 [code]add_exception[/code] 将它们添加到异常"
"列表中,通过设置碰撞层进行适当的过滤,或者通过类型掩ç è¿‡æ»¤ç‰©ä½“类型。\n"
"RayCast2D å¯ä»¥è¢«é…置为报告 [Area2D]([member collide_with_areas])和 "
@@ -66926,11 +66964,12 @@ msgid ""
"[code]body[/code] the [Node], if it exists in the tree, of the other "
"[PhysicsBody2D] or [TileMap]."
msgstr ""
-"当与å¦ä¸€ä¸ª[PhysicsBody2D]或[TileMap]å‘生碰撞时触å‘。需è¦å°†[member "
-"contact_monitor]设置为 [code]true[/code],并且将[member contacts_reported]设"
-"置得足够高以检测所有的碰撞。如果[TileSet]有碰撞[Shape2D],就会检测到[TileMap]"
-"的。\n"
-"[code]body[/code]是其他[PhysicsBody2D]或[TileMap]的[Node],如果它存在于树中。"
+"当与å¦ä¸€ä¸ª [PhysicsBody2D] 或 [TileMap] å‘生碰撞时触å‘。需è¦å°† [member "
+"contact_monitor] 设置为 [code]true[/code],并且将 [member contacts_reported] "
+"设置得足够高以检测所有的碰撞。如果[TileSet] 有碰撞 [Shape2D],就会检测到 "
+"[TileMap] 的。\n"
+"[code]body[/code] 是其他 [PhysicsBody2D] 或 [TileMap] 的 [Node],如果它存在于"
+"树中。"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -67001,20 +67040,22 @@ msgid ""
"RigidBody2D used by the [Physics2DServer]. Get the [CollisionShape2D] node "
"with [code]self.shape_owner_get_owner(local_shape_index)[/code]."
msgstr ""
-"当这个RigidBody2D的一个[Shape2D]å’Œå¦ä¸€ä¸ª[PhysicsBody2D]或[TileMap]çš„[Shape2D]"
-"ä¹‹é—´çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘ã€‚è¦æ±‚[member contact_monitor]设置为 [code]true[/code],"
-"[member contacts_reported]设置得足够高以检测所有的碰撞。如果[TileSet]有碰撞"
-"[Shape2D],就会检测到[TileMap]的。\n"
-"[code]body_rid[/code] [Physics2DServer]使用的其他[PhysicsBody2D]或[TileSet]的"
-"[CollisionObject2D]的 [RID]。\n"
-"[code]body[/code] å¦ä¸€ä¸ª[PhysicsBody2D]或[TileMap]çš„[Node],如果它存在于树"
-"中。\n"
-"[code]body_shape_index[/code] 由[Physics2DServer]使用的其他[PhysicsBody2D]或"
-"[TileMap]的[Shape2D]的索引。用[code]body."
-"shape_owner_get_owner(body_shape_index)[/code]获得[CollisionShape2D]节点。\n"
-"[code]local_shape_index[/code]这个RigidBody2D的[Shape2D]的索引,由"
-"[Physics2DServer]使用。用[code]self.shape_owner_get_owner(local_shape_index)"
-"[/code]获å–[CollisionShape2D]节点。"
+"当这个 RigidBody2D 的一个 [Shape2D] å’Œå¦ä¸€ä¸ª [PhysicsBody2D] 或 [TileMap] çš„ "
+"[Shape2D] ä¹‹é—´çš„ç¢°æ’žç»“æŸæ—¶è§¦å‘ã€‚è¦æ±‚ [member contact_monitor] 设置为 "
+"[code]true[/code],[member contacts_reported] 设置得足够高以检测所有的碰撞。"
+"如果 [TileSet] 有碰撞 [Shape2D],就会检测到 [TileMap] 的。\n"
+"[code]body_rid[/code] [Physics2DServer] 使用的其他 [PhysicsBody2D] 或 "
+"[TileSet] 的 [CollisionObject2D] 的 [RID]。\n"
+"[code]body[/code] å¦ä¸€ä¸ª [PhysicsBody2D] 或 [TileMap] çš„ [Node],如果它存在于"
+"树中。\n"
+"[code]body_shape_index[/code] 由 [Physics2DServer] 使用的其他 "
+"[PhysicsBody2D] 或 [TileMap] 的 [Shape2D]的索引。用 [code]body."
+"shape_owner_get_owner(body_shape_index)[/code] 获得 [CollisionShape2D] 节"
+"点。\n"
+"[code]local_shape_index[/code] 这个 RigidBody2D 的 [Shape2D] 的索引,由 "
+"[Physics2DServer] 使用。用 [code]self."
+"shape_owner_get_owner(local_shape_index)[/code] èŽ·å– [CollisionShape2D] 节"
+"点。"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -67032,14 +67073,14 @@ msgstr "陿€æ¨¡å¼ã€‚物体的行为就åƒä¸€ä¸ª[StaticBody2D],ä¸ä¼šç§»åЍã
msgid ""
"Character mode. Similar to [constant MODE_RIGID], but the body can not "
"rotate."
-msgstr "角色模å¼ã€‚与[constant MODE_RIGID]类似,但主体ä¸èƒ½æ—‹è½¬ã€‚"
+msgstr "角色模å¼ã€‚与 [constant MODE_RIGID] 类似,但主体ä¸èƒ½æ—‹è½¬ã€‚"
#: doc/classes/RigidBody2D.xml
msgid ""
"Kinematic mode. The body behaves like a [KinematicBody2D], and must be moved "
"by code."
msgstr ""
-"è¿åŠ¨å­¦æ¨¡å¼ã€‚这个物体的行为就åƒä¸€ä¸ª[KinematicBody2D]ï¼Œå¿…é¡»é€šè¿‡ä»£ç æ¥ç§»åŠ¨ã€‚"
+"è¿åŠ¨å­¦æ¨¡å¼ã€‚这个物体的行为就åƒä¸€ä¸ª [KinematicBody2D]ï¼Œå¿…é¡»é€šè¿‡ä»£ç æ¥ç§»åŠ¨ã€‚"
#: doc/classes/RigidBody2D.xml
msgid ""
@@ -67053,14 +67094,13 @@ msgstr ""
msgid ""
"Continuous collision detection enabled using raycasting. This is faster than "
"shapecasting but less precise."
-msgstr "使用射线投射å¯ç”¨è¿žç»­ç¢°æ’žæ£€æµ‹ã€‚这比 shapecasting 快,但精度较低。"
+msgstr "使用射线投射å¯ç”¨è¿žç»­ç¢°æ’žæ£€æµ‹ã€‚这比形状投射快,但精度较低。"
#: doc/classes/RigidBody2D.xml
msgid ""
"Continuous collision detection enabled using shapecasting. This is the "
"slowest CCD method and the most precise."
-msgstr ""
-"使用 shapecasting å¯ç”¨è¿žç»­ç¢°æ’žæ£€æµ‹ã€‚这是最慢的 CCD 方法,也是最精确的。"
+msgstr "使用形状投射å¯ç”¨è¿žç»­ç¢°æ’žæ£€æµ‹ã€‚这是最慢的 CCD 方法,也是最精确的。"
#: doc/classes/Room.xml
msgid "Room node, used to group objects together locally for [Portal] culling."
@@ -67611,8 +67651,8 @@ msgid ""
"scene as the result of [method PackedScene.get_state]."
msgstr ""
"维护一个与场景相关的资æºã€èŠ‚ç‚¹ã€å¯¼å‡ºçš„å’Œé‡å†™çš„属性以åŠå†…置脚本的列表。\n"
-"这个类ä¸èƒ½ç›´æŽ¥å®žä¾‹åŒ–,它是作为[method PackedScene.get_state]的结果为一个给定"
-"的场景检索的。"
+"这个类ä¸èƒ½ç›´æŽ¥å®žä¾‹åŒ–,它是作为 [method PackedScene.get_state] 的结果为一个给"
+"定的场景检索的。"
#: doc/classes/SceneState.xml
msgid ""
@@ -67640,7 +67680,7 @@ msgstr ""
#: doc/classes/SceneState.xml
msgid "Returns the method connected to the signal at [code]idx[/code]."
-msgstr "返回连接到[code]idx[/code]处信å·çš„æ–¹æ³•。"
+msgstr "返回连接到 [code]idx[/code] 处信å·çš„æ–¹æ³•。"
#: doc/classes/SceneState.xml
msgid "Returns the name of the signal at [code]idx[/code]."
@@ -67720,9 +67760,9 @@ msgid ""
"If [code]for_parent[/code] is [code]true[/code], returns the path of the "
"[code]idx[/code] node's parent instead."
msgstr ""
-"返回 [code]idx[/code]处的节点的路径。\n"
-"如果[code]for_parent[/code]是[code]true[/code],则返回 [code]idx[/code]节点的"
-"父节点的路径。"
+"返回 [code]idx[/code] 处的节点的路径。\n"
+"如果 [code]for_parent[/code] 是 [code]true[/code],则返回 [code]idx[/code] 节"
+"点的父节点的路径。"
#: doc/classes/SceneState.xml
msgid ""
@@ -67757,8 +67797,8 @@ msgid ""
"Returns [code]true[/code] if the node at [code]idx[/code] is an "
"[InstancePlaceholder]."
msgstr ""
-"如果[code]idx[/code]处的节点是一个[InstancePlaceholder],返回 [code]true[/"
-"code]。"
+"如果 [code]idx[/code] 处的节点是一个 [InstancePlaceholder],则返回 "
+"[code]true[/code]。"
#: doc/classes/SceneState.xml
msgid ""
@@ -67958,7 +67998,7 @@ msgstr "返回此 [SceneTree] 的 [member network_peer] 的唯一对等 ID。"
#: doc/classes/SceneTree.xml
msgid "Returns the number of nodes in this [SceneTree]."
-msgstr "返回此[SceneTree]中的节点数。"
+msgstr "返回此 [SceneTree] 中的节点数。"
#: doc/classes/SceneTree.xml
msgid "Returns a list of all nodes assigned to the given group."
@@ -67974,7 +68014,7 @@ msgstr ""
#: doc/classes/SceneTree.xml
msgid "Returns the sender's peer ID for the most recently received RPC call."
-msgstr "返回最近收到的RPC调用的å‘é€è€…的对等ID。"
+msgstr "返回最近收到的 RPC 调用的å‘é€è€…的对等 ID。"
#: doc/classes/SceneTree.xml
msgid "Returns [code]true[/code] if the given group exists."
@@ -68316,23 +68356,23 @@ msgstr "当 [SceneTree] 层次结构å‘生å˜åŒ–(移动或é‡å‘½åå­é¡¹ç­‰ï¼
#: doc/classes/SceneTree.xml
msgid "Call a group with no flags (default)."
-msgstr "调用没有标志的组(默认)。"
+msgstr "对组进行调用时,ä¸ä½¿ç”¨æ ‡å¿—(默认)。"
#: doc/classes/SceneTree.xml
msgid "Call a group in reverse scene order."
-msgstr "以相å的场景顺åºè°ƒç”¨ç»„。"
+msgstr "对组进行调用时,使用逆场景åºã€‚"
#: doc/classes/SceneTree.xml
msgid "Call a group immediately (calls are normally made on idle)."
-msgstr "ç«‹å³è°ƒç”¨ä¸€ä¸ªç»„(调用通常在空闲时进行)。"
+msgstr "å¯¹ç»„è¿›è¡Œè°ƒç”¨æ—¶ï¼Œç«‹å³æ‰§è¡Œï¼ˆæ­£å¸¸æƒ…况下是在空闲时调用的)。"
#: doc/classes/SceneTree.xml
msgid "Call a group only once even if the call is executed many times."
-msgstr "å³ä½¿è°ƒç”¨å¤šæ¬¡æ‰§è¡Œï¼Œä¹Ÿåªè°ƒç”¨ä¸€æ¬¡ç»„。"
+msgstr "对组进行调用时,å³ä¾¿æ‰§è¡Œäº†å¤šæ¬¡è°ƒç”¨ä¹Ÿåªè°ƒç”¨ä¸€æ¬¡ã€‚"
#: doc/classes/SceneTree.xml
msgid "No stretching."
-msgstr "未拉伸。"
+msgstr "䏿‹‰ä¼¸ã€‚"
#: doc/classes/SceneTree.xml
msgid "Render stretching in higher resolution (interpolated)."
@@ -68342,7 +68382,7 @@ msgstr "以更高的分辨率渲染拉伸(æ’值)。"
msgid ""
"Keep the specified display resolution. No interpolation. Content may appear "
"pixelated."
-msgstr "ä¿æŒæŒ‡å®šçš„æ˜¾ç¤ºåˆ†è¾¨çŽ‡ã€‚æ²¡æœ‰æ’值。内容å¯èƒ½ä¼šå‡ºçްåƒç´ åŒ–。"
+msgstr "ä¿æŒæŒ‡å®šçš„æ˜¾ç¤ºåˆ†è¾¨çŽ‡ã€‚ä¸åšæ’值。内容å¯èƒ½ä¼šå‡ºçްåƒç´ åŒ–。"
#: doc/classes/SceneTree.xml
msgid ""
@@ -68360,13 +68400,13 @@ msgstr "在任æ„轴上用黑æ¡å¡«å……æ¥ä¿æŒç›¸åŒçš„长宽比。这å¯ä»¥é˜²
msgid ""
"Expand vertically. Left/right black bars may appear if the window is too "
"wide."
-msgstr "垂直展开。如果窗å£å¤ªå®½ï¼Œå¯èƒ½ä¼šå‡ºçް左/å³é»‘æ¡ã€‚"
+msgstr "垂直扩展。如果窗å£å¤ªå®½ï¼Œå¯èƒ½ä¼šå‡ºçް左/å³é»‘æ¡ã€‚"
#: doc/classes/SceneTree.xml
msgid ""
"Expand horizontally. Top/bottom black bars may appear if the window is too "
"tall."
-msgstr "水平展开。如果窗å£å¤ªé«˜ï¼Œå¯èƒ½ä¼šå‡ºçŽ°é¡¶éƒ¨/底部黑æ¡ã€‚"
+msgstr "水平扩展。如果窗å£å¤ªé«˜ï¼Œå¯èƒ½ä¼šå‡ºçŽ°é¡¶éƒ¨/底部黑æ¡ã€‚"
#: doc/classes/SceneTree.xml
msgid ""
@@ -68393,9 +68433,9 @@ msgid ""
"The timer will be dereferenced after its time elapses. To preserve the "
"timer, you can keep a reference to it. See [Reference]."
msgstr ""
-"由场景树管ç†çš„ä¸€æ¬¡æ€§å®šæ—¶å™¨ï¼Œå®ƒåœ¨å®Œæˆæ—¶å‘[signal timeout] ä¿¡å·ã€‚请å‚阅 "
+"由场景树管ç†çš„ä¸€æ¬¡æ€§å®šæ—¶å™¨ï¼Œå®ƒåœ¨å®Œæˆæ—¶å‘ [signal timeout] ä¿¡å·ã€‚å¦è¯·å‚阅 "
"[method SceneTree.create_timer]。\n"
-"与 [Timer] 相å,它ä¸éœ€è¦å®žä¾‹åŒ–节点。常用于创建一次性的延迟定时器,如下é¢çš„例"
+"与 [Timer] ä¸åŒï¼Œå®ƒä¸éœ€è¦å®žä¾‹åŒ–节点。常用于创建一次性的延迟定时器,如下é¢çš„例"
"å­ï¼š\n"
"[codeblock]\n"
"func some_function():\n"
@@ -73594,9 +73634,32 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
-"æ ¼å¼åŒ–字符串,将所有的 [code]placeholder[/code] 替æ¢ä¸º [code]values[/code]。"
#: doc/classes/String.xml
msgid "If the string is a valid file path, returns the base directory name."
@@ -74414,13 +74477,12 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
-"使用具有给定 [RID] 的 [CanvasItem] 绘制此StyleBox。\n"
-"您å¯ä»¥åœ¨ [CanvasItem] 派生节点上使用 [method Object.get_instance_id] èŽ·å– "
-"[RID] 值。"
#: doc/classes/StyleBox.xml
msgid "Returns the size of this [StyleBox] without the margins."
@@ -76272,6 +76334,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr "为 [code]true[/code] æ—¶å³é”®å•击会显示上下文èœå•。"
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "如果为 [code]true[/code],则å¯ä»¥é€‰æ‹©å’Œç¼–辑该值。"
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -83788,12 +83855,14 @@ msgid "The subdivision amount of the fourth quadrant on the shadow atlas."
msgstr "阴影图集上第四象é™çš„细分é‡ã€‚"
#: doc/classes/Viewport.xml
+#, fuzzy
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
"阴影图集的分辨率(用于全å‘光和èšå…‰ï¼‰ã€‚该值将四èˆäº”入到最接近的 2 的幂。\n"
"[b]注æ„:[/b]如果设置为 0,阴影将ä¸å¯è§ã€‚由于用户创建的视区默认值为 0,因此必"
@@ -83830,8 +83899,12 @@ msgid ""
msgstr "如果为 [code]true[/code]ï¼Œè¯¥è§†çª—åº”ä½¿å…¶èƒŒæ™¯æ¸²æŸ“ä¸ºé€æ˜Žã€‚"
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
-msgstr "视窗的渲染模å¼ã€‚"
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
+msgstr ""
#: doc/classes/Viewport.xml
msgid ""
diff --git a/doc/translations/zh_TW.po b/doc/translations/zh_TW.po
index 84b16d22a6..63312338fc 100644
--- a/doc/translations/zh_TW.po
+++ b/doc/translations/zh_TW.po
@@ -12257,10 +12257,12 @@ msgid ""
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_physics_process[/code] callback."
msgstr ""
#: doc/classes/Camera2D.xml doc/classes/ClippedCamera.xml
+#: doc/classes/InterpolatedCamera.xml
msgid "The camera updates with the [code]_process[/code] callback."
msgstr ""
@@ -19559,13 +19561,17 @@ msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"Amount of extra bias for shadow splits that are far away. If self-shadowing "
-"occurs only on the splits far away, increasing this value can fix them."
+"occurs only on the splits far away, increasing this value can fix them. This "
+"is ignored when [member directional_shadow_mode] is [constant "
+"SHADOW_ORTHOGONAL]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"If [code]true[/code], shadow detail is sacrificed in exchange for smoother "
-"transitions between splits."
+"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]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19575,7 +19581,11 @@ msgid ""
msgstr ""
#: doc/classes/DirectionalLight.xml
-msgid "The maximum distance for shadow splits."
+msgid ""
+"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)."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -19592,23 +19602,23 @@ msgstr ""
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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_2_SPLITS[/code] or "
-"[code]SHADOW_PARALLEL_4_SPLITS[/code]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant "
+"SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
msgid ""
"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]."
+"directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS]."
msgstr ""
#: doc/classes/DirectionalLight.xml
@@ -29977,7 +29987,10 @@ msgid ""
"input at the cost of increased CPU usage. In applications where drawing "
"freehand lines is required, input accumulation should generally be disabled "
"while the user is drawing the line to get results that closely follow the "
-"actual input."
+"actual input.\n"
+"[b]Note:[/b] Input accumulation is [i]disabled[/i] by default for backward "
+"compatibility reasons. It is however recommended to enable it for games "
+"which don't require very reactive input, as this will decrease CPU usage."
msgstr ""
#: doc/classes/Input.xml
@@ -30551,10 +30564,11 @@ msgstr ""
msgid ""
"Contains mouse and pen motion information. Supports relative, absolute "
"positions and speed. See [method Node._input].\n"
-"[b]Note:[/b] By default, this event is only emitted once per frame rendered "
-"at most. If you need more precise input reporting, set [member Input."
-"use_accumulated_input] to [code]false[/code] to make events emitted as often "
-"as possible. If you use InputEventMouseMotion to draw lines, consider "
+"[b]Note:[/b] By default, this event can be emitted multiple times per frame "
+"rendered, allowing for precise input reporting, at the expense of CPU usage. "
+"You can set [member Input.use_accumulated_input] to [code]true[/code] to let "
+"multiple events merge into a single emitted event per frame.\n"
+"[b]Note:[/b] If you use InputEventMouseMotion to draw lines, consider "
"implementing [url=https://en.wikipedia.org/wiki/"
"Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to "
"avoid visible gaps in lines if the user is moving the mouse quickly."
@@ -30878,6 +30892,11 @@ msgstr ""
#: doc/classes/InterpolatedCamera.xml
msgid ""
+"The camera's process callback. See [enum InterpolatedCameraProcessMode]."
+msgstr ""
+
+#: doc/classes/InterpolatedCamera.xml
+msgid ""
"How quickly the camera moves toward its target. Higher values will result in "
"tighter camera motion."
msgstr ""
@@ -36311,7 +36330,7 @@ msgid ""
"maximum distance is exceeded, it recalculates the ideal path."
msgstr ""
-#: doc/classes/NavigationAgent.xml doc/classes/NavigationAgent2D.xml
+#: doc/classes/NavigationAgent.xml
msgid ""
"The radius of the avoidance agent. This is the \"body\" of the avoidance "
"agent and not the avoidance maneuver starting radius (which is controlled by "
@@ -36424,6 +36443,14 @@ msgid ""
"least one matching layer."
msgstr ""
+#: doc/classes/NavigationAgent2D.xml
+msgid ""
+"The radius of the avoidance agent. This is the \"body\" of the avoidance "
+"agent and not the avoidance maneuver starting radius (which is controlled by "
+"[member neighbor_dist]).\n"
+"Does not affect normal pathfinding."
+msgstr ""
+
#: doc/classes/NavigationMesh.xml
msgid "A mesh to approximate the walkable areas and obstacles."
msgstr ""
@@ -50041,8 +50068,8 @@ msgstr ""
#: doc/classes/ProjectSettings.xml
msgid ""
-"Size for shadow atlas (used for OmniLights and SpotLights). See "
-"documentation."
+"Size for shadow atlas (used for OmniLights and SpotLights). The value will "
+"be rounded up to the nearest power of 2. See shadow mapping documentation."
msgstr ""
#: doc/classes/ProjectSettings.xml
@@ -58417,7 +58444,31 @@ msgstr ""
#: doc/classes/String.xml
msgid ""
"Formats the string by replacing all occurrences of [code]placeholder[/code] "
-"with [code]values[/code]."
+"with the elements of [code]values[/code].\n"
+"[code]values[/code] can be a [Dictionary] or an [Array]. Any underscores in "
+"[code]placeholder[/code] will be replaced with the corresponding keys in "
+"advance. Array elements use their index as keys.\n"
+"[codeblock]\n"
+"# Prints: Waiting for Godot is a play by Samuel Beckett, and Godot Engine is "
+"named after it.\n"
+"var use_array_values = \"Waiting for {0} is a play by {1}, and {0} Engine is "
+"named after it.\"\n"
+"print(use_array_values.format([\"Godot\", \"Samuel Beckett\"]))\n"
+"\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {id} is {name}.\".format({\"id\": 42, \"name\": \"Godot\"}))\n"
+"[/codeblock]\n"
+"Some additional handling is performed when [code]values[/code] is an array. "
+"If [code]placeholder[/code] does not contain an underscore, the elements of "
+"the array will be used to replace one occurrence of the placeholder in turn; "
+"If an array element is another 2-element array, it'll be interpreted as a "
+"key-value pair.\n"
+"[codeblock]\n"
+"# Prints: User 42 is Godot.\n"
+"print(\"User {} is {}.\".format([42, \"Godot\"], \"{}\"))\n"
+"print(\"User {id} is {name}.\".format([[\"id\", 42], [\"name\", "
+"\"Godot\"]]))\n"
+"[/codeblock]"
msgstr ""
#: doc/classes/String.xml
@@ -59014,9 +59065,11 @@ msgstr ""
#: doc/classes/StyleBox.xml
msgid ""
-"Draws this stylebox using a [CanvasItem] with given [RID].\n"
-"You can get a [RID] value using [method Object.get_instance_id] on a "
-"[CanvasItem]-derived node."
+"Draws this stylebox using a canvas item identified by the given [RID].\n"
+"The [RID] value can either be the result of [method CanvasItem."
+"get_canvas_item] called on an existing [CanvasItem]-derived node, or "
+"directly from creating a canvas item in the [VisualServer] with [method "
+"VisualServer.canvas_item_create]."
msgstr ""
#: doc/classes/StyleBox.xml
@@ -60562,6 +60615,11 @@ msgid "If [code]true[/code], a right-click displays the context menu."
msgstr ""
#: doc/classes/TextEdit.xml
+#, fuzzy
+msgid "If [code]true[/code], allow drag and drop of selected text."
+msgstr "å›žå‚³åƒæ•¸çš„餘弦值。"
+
+#: doc/classes/TextEdit.xml
msgid ""
"If [code]true[/code], the \"space\" character will have a visible "
"representation."
@@ -66655,9 +66713,10 @@ msgstr ""
msgid ""
"The shadow atlas' resolution (used for omni and spot lights). The value will "
"be rounded up to the nearest power of 2.\n"
-"[b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-"
-"created viewports default to a value of 0, this value must be set above 0 "
-"manually."
+"[b]Note:[/b] If this is set to [code]0[/code], both point [i]and[/i] "
+"directional shadows won't be visible. Since user-created viewports default "
+"to a value of [code]0[/code], this value must be set above [code]0[/code] "
+"manually (typically at least [code]256[/code])."
msgstr ""
#: doc/classes/Viewport.xml
@@ -66686,7 +66745,11 @@ msgid ""
msgstr ""
#: doc/classes/Viewport.xml
-msgid "The rendering mode of viewport."
+msgid ""
+"The rendering mode of viewport.\n"
+"[b]Note:[/b] If set to [constant USAGE_2D] or [constant "
+"USAGE_2D_NO_SAMPLING], [member hdr] will have no effect when enabled since "
+"HDR is not supported for 2D."
msgstr ""
#: doc/classes/Viewport.xml
diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp
new file mode 100644
index 0000000000..02d88f6871
--- /dev/null
+++ b/drivers/gles3/environment/fog.cpp
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* fog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "fog.h"
+
+using namespace GLES3;
+
+/* FOG */
+
+RID Fog::fog_volume_allocate() {
+ return RID();
+}
+
+void Fog::fog_volume_initialize(RID p_rid) {
+}
+
+void Fog::fog_free(RID p_rid) {
+}
+
+void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
+}
+
+void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+}
+
+void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) {
+}
+
+AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {
+ return AABB();
+}
+
+RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const {
+ return RS::FOG_VOLUME_SHAPE_BOX;
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h
new file mode 100644
index 0000000000..22bf3bb017
--- /dev/null
+++ b/drivers/gles3/environment/fog.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FOG_GLES3_H
+#define FOG_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/environment/renderer_fog.h"
+
+namespace GLES3 {
+
+class Fog : public RendererFog {
+public:
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() override;
+ virtual void fog_volume_initialize(RID p_rid) override;
+ virtual void fog_free(RID p_rid) override;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !FOG_GLES3_H
diff --git a/drivers/gles3/environment/gi.cpp b/drivers/gles3/environment/gi.cpp
index 98d698b2ae..84cdb81d35 100644
--- a/drivers/gles3/environment/gi.cpp
+++ b/drivers/gles3/environment/gi.cpp
@@ -126,13 +126,6 @@ bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
return false;
}
-void GI::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
-}
-
-float GI::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
- return 0;
-}
-
uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const {
return 0;
}
diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h
index bff482d7fa..b633520784 100644
--- a/drivers/gles3/environment/gi.h
+++ b/drivers/gles3/environment/gi.h
@@ -86,9 +86,6 @@ public:
virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override;
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override;
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override;
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override;
-
virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override;
};
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index d41c844d1d..82f7450bc2 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -34,12 +34,12 @@
#include "core/os/os.h"
#include "rasterizer_scene_gles3.h"
-#include "rasterizer_storage_gles3.h"
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_server_default.h"
#include "storage/config.h"
#include "storage/material_storage.h"
+#include "storage/mesh_storage.h"
#include "storage/texture_storage.h"
#ifndef GLES_OVER_GL
@@ -1416,9 +1416,8 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
return singleton;
}
-RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) {
+RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
singleton = this;
- storage = p_storage;
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index bf13c91e1c..caf649aaf6 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -34,7 +34,6 @@
#ifdef GLES3_ENABLED
#include "rasterizer_scene_gles3.h"
-#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
#include "storage/material_storage.h"
@@ -204,8 +203,6 @@ public:
typedef void Texture;
- RasterizerStorageGLES3 *storage = nullptr;
-
void canvas_begin(RID p_to_render_target, bool p_to_backbuffer);
//virtual void draw_window_margins(int *black_margin, RID *black_image) override;
@@ -260,7 +257,7 @@ public:
void set_time(double p_time);
static RasterizerCanvasGLES3 *get_singleton();
- RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage);
+ RasterizerCanvasGLES3();
~RasterizerCanvasGLES3();
};
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 78ffb42557..613a7f37d9 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "rasterizer_gles3.h"
+#include "storage/utilities.h"
#ifdef GLES3_ENABLED
@@ -99,8 +100,9 @@ void RasterizerGLES3::begin_frame(double frame_step) {
canvas->set_time(time_total);
scene->set_time(time_total, frame_step);
- storage->info.render_final = storage->info.render;
- storage->info.render.reset();
+ GLES3::Utilities *utilities = GLES3::Utilities::get_singleton();
+ utilities->info.render_final = utilities->info.render;
+ utilities->info.render.reset();
//scene->iteration();
}
@@ -197,14 +199,15 @@ void RasterizerGLES3::initialize() {
void RasterizerGLES3::finalize() {
memdelete(scene);
memdelete(canvas);
- memdelete(storage);
memdelete(gi);
+ memdelete(fog);
memdelete(copy_effects);
memdelete(light_storage);
memdelete(particles_storage);
memdelete(mesh_storage);
memdelete(material_storage);
memdelete(texture_storage);
+ memdelete(utilities);
memdelete(config);
}
@@ -265,6 +268,7 @@ RasterizerGLES3::RasterizerGLES3() {
// OpenGL needs to be initialized before initializing the Rasterizers
config = memnew(GLES3::Config);
+ utilities = memnew(GLES3::Utilities);
texture_storage = memnew(GLES3::TextureStorage);
material_storage = memnew(GLES3::MaterialStorage);
mesh_storage = memnew(GLES3::MeshStorage);
@@ -272,9 +276,9 @@ RasterizerGLES3::RasterizerGLES3() {
light_storage = memnew(GLES3::LightStorage);
copy_effects = memnew(GLES3::CopyEffects);
gi = memnew(GLES3::GI);
- storage = memnew(RasterizerStorageGLES3);
- canvas = memnew(RasterizerCanvasGLES3(storage));
- scene = memnew(RasterizerSceneGLES3(storage));
+ fog = memnew(GLES3::Fog);
+ canvas = memnew(RasterizerCanvasGLES3());
+ scene = memnew(RasterizerSceneGLES3());
}
RasterizerGLES3::~RasterizerGLES3() {
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index c0322dc45b..e842b6d70c 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -34,10 +34,10 @@
#ifdef GLES3_ENABLED
#include "effects/copy_effects.h"
+#include "environment/fog.h"
#include "environment/gi.h"
#include "rasterizer_canvas_gles3.h"
#include "rasterizer_scene_gles3.h"
-#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_compositor.h"
#include "storage/config.h"
#include "storage/light_storage.h"
@@ -45,6 +45,7 @@
#include "storage/mesh_storage.h"
#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
+#include "storage/utilities.h"
class RasterizerGLES3 : public RendererCompositor {
private:
@@ -55,27 +56,29 @@ private:
protected:
GLES3::Config *config = nullptr;
+ GLES3::Utilities *utilities = nullptr;
GLES3::TextureStorage *texture_storage = nullptr;
GLES3::MaterialStorage *material_storage = nullptr;
GLES3::MeshStorage *mesh_storage = nullptr;
GLES3::ParticlesStorage *particles_storage = nullptr;
GLES3::LightStorage *light_storage = nullptr;
GLES3::GI *gi = nullptr;
+ GLES3::Fog *fog = nullptr;
GLES3::CopyEffects *copy_effects = nullptr;
- RasterizerStorageGLES3 *storage = nullptr;
RasterizerCanvasGLES3 *canvas = nullptr;
RasterizerSceneGLES3 *scene = nullptr;
void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect);
public:
+ RendererUtilities *get_utilities() { return utilities; }
RendererLightStorage *get_light_storage() { return light_storage; }
RendererMaterialStorage *get_material_storage() { return material_storage; }
RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
RendererParticlesStorage *get_particles_storage() { return particles_storage; }
RendererTextureStorage *get_texture_storage() { return texture_storage; }
RendererGI *get_gi() { return gi; }
- RendererStorage *get_storage() { return storage; }
+ RendererFog *get_fog() { return fog; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 33c7b9bf32..989d0de496 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -33,6 +33,9 @@
#include "core/templates/sort_array.h"
#include "servers/rendering/rendering_server_default.h"
#include "storage/config.h"
+#include "storage/light_storage.h"
+#include "storage/mesh_storage.h"
+#include "storage/texture_storage.h"
#ifdef GLES3_ENABLED
@@ -45,7 +48,7 @@ RasterizerSceneGLES3 *RasterizerSceneGLES3::get_singleton() {
}
RendererSceneRender::GeometryInstance *RasterizerSceneGLES3::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+ RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
GeometryInstanceGLES3 *ginstance = geometry_instance_alloc.alloc();
@@ -285,16 +288,16 @@ void RasterizerSceneGLES3::_update_dirty_geometry_instances() {
}
}
-void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RasterizerSceneGLES3::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL:
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceGLES3 *ginstance = static_cast<GeometryInstanceGLES3 *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
@@ -306,7 +309,7 @@ void RasterizerSceneGLES3::_geometry_instance_dependency_changed(RendererStorage
}
}
-void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+void RasterizerSceneGLES3::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RasterizerSceneGLES3 *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
}
@@ -376,7 +379,7 @@ void RasterizerSceneGLES3::_geometry_instance_add_surface_with_material(Geometry
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
- storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
}
//shadow
@@ -1609,10 +1612,10 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
correction.set_depth_correction(p_flip_y);
CameraMatrix projection = correction * p_render_data->cam_projection;
//store camera into ubo
- RasterizerStorageGLES3::store_camera(projection, scene_state.ubo.projection_matrix);
- RasterizerStorageGLES3::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RasterizerStorageGLES3::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
- RasterizerStorageGLES3::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix);
+ GLES3::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
+ GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
+ GLES3::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
+ GLES3::MaterialStorage::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix);
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
@@ -1659,7 +1662,7 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
Basis sky_transform = env->sky_orientation;
sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis;
- RasterizerStorageGLES3::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
+ GLES3::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
}
@@ -1974,7 +1977,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
if (p_render_buffers.is_valid()) {
clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
} else {
- clear_color = storage->get_default_clear_color();
+ clear_color = texture_storage->get_default_clear_color();
}
Environment *env = environment_owner.get_or_null(p_environment);
@@ -2657,12 +2660,10 @@ void RasterizerSceneGLES3::decals_set_filter(RS::DecalFilter p_filter) {
void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter p_filter) {
}
-RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {
+RasterizerSceneGLES3::RasterizerSceneGLES3() {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
- storage = p_storage;
-
{
// Setup Lights
@@ -2870,15 +2871,15 @@ RasterizerSceneGLES3::~RasterizerSceneGLES3() {
// Scene Shader
GLES3::MaterialStorage::get_singleton()->shaders.scene_shader.version_free(scene_globals.shader_default_version);
GLES3::MaterialStorage::get_singleton()->shaders.cubemap_filter_shader.version_free(scene_globals.cubemap_filter_shader_version);
- storage->free(scene_globals.default_material);
- storage->free(scene_globals.default_shader);
+ RSG::material_storage->material_free(scene_globals.default_material);
+ RSG::material_storage->shader_free(scene_globals.default_shader);
// Sky Shader
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version);
- storage->free(sky_globals.default_material);
- storage->free(sky_globals.default_shader);
- storage->free(sky_globals.fog_material);
- storage->free(sky_globals.fog_shader);
+ RSG::material_storage->material_free(sky_globals.default_material);
+ RSG::material_storage->shader_free(sky_globals.default_shader);
+ RSG::material_storage->material_free(sky_globals.fog_material);
+ RSG::material_storage->shader_free(sky_globals.fog_shader);
glDeleteBuffers(1, &sky_globals.screen_triangle);
glDeleteVertexArrays(1, &sky_globals.screen_triangle_array);
glDeleteTextures(1, &sky_globals.radical_inverse_vdc_cache_tex);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 4757a3f161..53b76011fe 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -37,7 +37,6 @@
#include "core/templates/paged_allocator.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
-#include "rasterizer_storage_gles3.h"
#include "scene/resources/mesh.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -45,6 +44,8 @@
#include "shader_gles3.h"
#include "shaders/cubemap_filter.glsl.gen.h"
#include "shaders/sky.glsl.gen.h"
+#include "storage/material_storage.h"
+#include "storage/utilities.h"
enum RenderListType {
RENDER_LIST_OPAQUE, //used for opaque objects
@@ -125,7 +126,6 @@ struct RenderDataGLES3 {
RendererScene::RenderInfo *render_info = nullptr;
};
-class RasterizerStorageGLES3;
class RasterizerCanvasGLES3;
class RasterizerSceneGLES3 : public RendererSceneRender {
@@ -323,7 +323,7 @@ private:
bool mirror = false;
bool dirty_dependencies = false;
- RendererStorage::DependencyTracker dependency_tracker;
+ DependencyTracker dependency_tracker;
};
Data *data = nullptr;
@@ -345,8 +345,8 @@ private:
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
};
- static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
- static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceGLES3>::List geometry_instance_dirty_list;
@@ -739,7 +739,6 @@ protected:
void _free_sky_data(Sky *p_sky);
public:
- RasterizerStorageGLES3 *storage;
RasterizerCanvasGLES3 *canvas;
GeometryInstance *geometry_instance_create(RID p_base) override;
@@ -943,7 +942,7 @@ public:
void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
static RasterizerSceneGLES3 *get_singleton();
- RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage);
+ RasterizerSceneGLES3();
~RasterizerSceneGLES3();
};
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
deleted file mode 100644
index 3b80d88666..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-/*************************************************************************/
-/* rasterizer_storage_gles3.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "rasterizer_storage_gles3.h"
-
-#ifdef GLES3_ENABLED
-
-#include "core/config/project_settings.h"
-#include "core/math/transform_3d.h"
-// #include "rasterizer_canvas_gles3.h"
-#include "rasterizer_scene_gles3.h"
-#include "servers/rendering/shader_language.h"
-
-/* MISC */
-
-void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_base)) {
- GLES3::Mesh *mesh = GLES3::MeshStorage::get_singleton()->get_mesh(p_base);
- p_instance->update_dependency(&mesh->dependency);
- } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
- GLES3::MultiMesh *multimesh = GLES3::MeshStorage::get_singleton()->get_multimesh(p_base);
- p_instance->update_dependency(&multimesh->dependency);
- if (multimesh->mesh.is_valid()) {
- base_update_dependency(multimesh->mesh, p_instance);
- }
- } else if (GLES3::LightStorage::get_singleton()->owns_light(p_base)) {
- GLES3::Light *l = GLES3::LightStorage::get_singleton()->get_light(p_base);
- p_instance->update_dependency(&l->dependency);
- }
-}
-
-Vector<uint8_t> RasterizerStorageGLES3::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) {
- Vector<uint8_t> ret;
- ret.resize(p_buffer_size);
- glBindBuffer(p_target, p_buffer);
-
-#if defined(__EMSCRIPTEN__)
- {
- uint8_t *w = ret.ptrw();
- glGetBufferSubData(p_target, 0, p_buffer_size, w);
- }
-#else
- void *data = glMapBufferRange(p_target, 0, p_buffer_size, GL_MAP_READ_BIT);
- ERR_FAIL_NULL_V(data, Vector<uint8_t>());
- {
- uint8_t *w = ret.ptrw();
- memcpy(w, data, p_buffer_size);
- }
- glUnmapBuffer(p_target);
-#endif
- glBindBuffer(p_target, 0);
- return ret;
-}
-
-/* OCCLUDER */
-
-void RasterizerStorageGLES3::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {
-}
-
-/* FOG */
-
-RID RasterizerStorageGLES3::fog_volume_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::fog_volume_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
-}
-
-void RasterizerStorageGLES3::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
-}
-
-void RasterizerStorageGLES3::fog_volume_set_material(RID p_fog_volume, RID p_material) {
-}
-
-AABB RasterizerStorageGLES3::fog_volume_get_aabb(RID p_fog_volume) const {
- return AABB();
-}
-
-RS::FogVolumeShape RasterizerStorageGLES3::fog_volume_get_shape(RID p_fog_volume) const {
- return RS::FOG_VOLUME_SHAPE_BOX;
-}
-
-/* VISIBILITY NOTIFIER */
-RID RasterizerStorageGLES3::visibility_notifier_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::visibility_notifier_initialize(RID p_notifier) {
-}
-
-void RasterizerStorageGLES3::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
-}
-
-void RasterizerStorageGLES3::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
-}
-
-AABB RasterizerStorageGLES3::visibility_notifier_get_aabb(RID p_notifier) const {
- return AABB();
-}
-
-void RasterizerStorageGLES3::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
-}
-
-/* CANVAS SHADOW */
-
-RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
- CanvasLightShadow *cls = memnew(CanvasLightShadow);
-
- if (p_width > config->max_texture_size) {
- p_width = config->max_texture_size;
- }
-
- cls->size = p_width;
- cls->height = 16;
-
- glActiveTexture(GL_TEXTURE0);
-
- glGenFramebuffers(1, &cls->fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
-
- glGenRenderbuffers(1, &cls->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
-
- glGenTextures(1, &cls->distance);
- glBindTexture(GL_TEXTURE_2D, cls->distance);
- if (config->use_rgba_2d_shadows) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, nullptr);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- //printf("errnum: %x\n",status);
- glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- memdelete(cls);
- ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
- }
-
- return canvas_light_shadow_owner.make_rid(cls);
-}
-
-/* LIGHT SHADOW MAPPING */
-/*
-
-RID RasterizerStorageGLES3::canvas_light_occluder_create() {
- CanvasOccluder *co = memnew(CanvasOccluder);
- co->index_id = 0;
- co->vertex_id = 0;
- co->len = 0;
-
- return canvas_occluder_owner.make_rid(co);
-}
-
-void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {
- CanvasOccluder *co = canvas_occluder_owner.get(p_occluder);
- ERR_FAIL_COND(!co);
-
- co->lines = p_lines;
-
- if (p_lines.size() != co->len) {
- if (co->index_id) {
- glDeleteBuffers(1, &co->index_id);
- } if (co->vertex_id) {
- glDeleteBuffers(1, &co->vertex_id);
- }
-
- co->index_id = 0;
- co->vertex_id = 0;
- co->len = 0;
- }
-
- if (p_lines.size()) {
- PoolVector<float> geometry;
- PoolVector<uint16_t> indices;
- int lc = p_lines.size();
-
- geometry.resize(lc * 6);
- indices.resize(lc * 3);
-
- PoolVector<float>::Write vw = geometry.write();
- PoolVector<uint16_t>::Write iw = indices.write();
-
- PoolVector<Vector2>::Read lr = p_lines.read();
-
- const int POLY_HEIGHT = 16384;
-
- for (int i = 0; i < lc / 2; i++) {
- vw[i * 12 + 0] = lr[i * 2 + 0].x;
- vw[i * 12 + 1] = lr[i * 2 + 0].y;
- vw[i * 12 + 2] = POLY_HEIGHT;
-
- vw[i * 12 + 3] = lr[i * 2 + 1].x;
- vw[i * 12 + 4] = lr[i * 2 + 1].y;
- vw[i * 12 + 5] = POLY_HEIGHT;
-
- vw[i * 12 + 6] = lr[i * 2 + 1].x;
- vw[i * 12 + 7] = lr[i * 2 + 1].y;
- vw[i * 12 + 8] = -POLY_HEIGHT;
-
- vw[i * 12 + 9] = lr[i * 2 + 0].x;
- vw[i * 12 + 10] = lr[i * 2 + 0].y;
- vw[i * 12 + 11] = -POLY_HEIGHT;
-
- iw[i * 6 + 0] = i * 4 + 0;
- iw[i * 6 + 1] = i * 4 + 1;
- iw[i * 6 + 2] = i * 4 + 2;
-
- iw[i * 6 + 3] = i * 4 + 2;
- iw[i * 6 + 4] = i * 4 + 3;
- iw[i * 6 + 5] = i * 4 + 0;
- }
-
- //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
-
- if (!co->vertex_id) {
- glGenBuffers(1, &co->vertex_id);
- glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
- glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW);
- } else {
- glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
- glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr());
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
-
- if (!co->index_id) {
- glGenBuffers(1, &co->index_id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW);
- } else {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr());
- }
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
-
- co->len = lc;
- }
-}
-*/
-
-RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
- if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
- return RS::INSTANCE_MESH;
- } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
- return RS::INSTANCE_MULTIMESH;
- } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
- return RS::INSTANCE_LIGHT;
- }
- return RS::INSTANCE_NONE;
-}
-
-bool RasterizerStorageGLES3::free(RID p_rid) {
- if (GLES3::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
- GLES3::TextureStorage::get_singleton()->render_target_free(p_rid);
- return true;
- } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) {
- GLES3::TextureStorage::get_singleton()->texture_free(p_rid);
- return true;
- } else if (GLES3::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
- GLES3::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
- return true;
- } else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
- GLES3::MaterialStorage::get_singleton()->shader_free(p_rid);
- return true;
- } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
- GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
- return true;
- } else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
- GLES3::MeshStorage::get_singleton()->mesh_free(p_rid);
- return true;
- } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
- GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid);
- return true;
- } else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
- GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
- return true;
- } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
- GLES3::LightStorage::get_singleton()->light_free(p_rid);
- return true;
- } else {
- return false;
- }
- /*
- else if (reflection_probe_owner.owns(p_rid)) {
- // delete the texture
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
- reflection_probe->instance_remove_deps();
-
- reflection_probe_owner.free(p_rid);
- memdelete(reflection_probe);
-
- return true;
- } else if (lightmap_capture_data_owner.owns(p_rid)) {
- // delete the texture
- LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get_or_null(p_rid);
- lightmap_capture->instance_remove_deps();
-
- lightmap_capture_data_owner.free(p_rid);
- memdelete(lightmap_capture);
- return true;
-
- } else if (canvas_occluder_owner.owns(p_rid)) {
- CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid);
- if (co->index_id) {
- glDeleteBuffers(1, &co->index_id);
- }
- if (co->vertex_id) {
- glDeleteBuffers(1, &co->vertex_id);
- }
-
- canvas_occluder_owner.free(p_rid);
- memdelete(co);
-
- return true;
-
- } else if (canvas_light_shadow_owner.owns(p_rid)) {
- CanvasLightShadow *cls = canvas_light_shadow_owner.get_or_null(p_rid);
- glDeleteFramebuffers(1, &cls->fbo);
- glDeleteRenderbuffers(1, &cls->depth);
- glDeleteTextures(1, &cls->distance);
- canvas_light_shadow_owner.free(p_rid);
- memdelete(cls);
-
- return true;
- */
-}
-
-bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
- if (!config) {
- return false;
- }
-
- if (p_feature == "rgtc") {
- return config->rgtc_supported;
- }
-
- if (p_feature == "s3tc") {
- return config->s3tc_supported;
- }
-
- if (p_feature == "bptc") {
- return config->bptc_supported;
- }
-
- if (p_feature == "etc" || p_feature == "etc2") {
- return config->etc2_supported;
- }
-
- return false;
-}
-
-////////////////////////////////////////////
-
-void RasterizerStorageGLES3::set_debug_generate_wireframes(bool p_generate) {
-}
-
-//void RasterizerStorageGLES3::render_info_begin_capture() {
-// info.snap = info.render;
-//}
-
-//void RasterizerStorageGLES3::render_info_end_capture() {
-// info.snap.object_count = info.render.object_count - info.snap.object_count;
-// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count;
-// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count;
-// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count;
-// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count;
-// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count;
-// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count;
-// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count;
-//}
-
-//int RasterizerStorageGLES3::get_captured_render_info(RS::RenderInfo p_info) {
-// switch (p_info) {
-// case RS::INFO_OBJECTS_IN_FRAME: {
-// return info.snap.object_count;
-// } break;
-// case RS::INFO_VERTICES_IN_FRAME: {
-// return info.snap.vertices_count;
-// } break;
-// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: {
-// return info.snap.material_switch_count;
-// } break;
-// case RS::INFO_SHADER_CHANGES_IN_FRAME: {
-// return info.snap.shader_rebind_count;
-// } break;
-// case RS::INFO_SURFACE_CHANGES_IN_FRAME: {
-// return info.snap.surface_switch_count;
-// } break;
-// case RS::INFO_DRAW_CALLS_IN_FRAME: {
-// return info.snap.draw_call_count;
-// } break;
-// /*
-// case RS::INFO_2D_ITEMS_IN_FRAME: {
-// return info.snap._2d_item_count;
-// } break;
-// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: {
-// return info.snap._2d_draw_call_count;
-// } break;
-// */
-// default: {
-// return get_render_info(p_info);
-// }
-// }
-//}
-
-//int RasterizerStorageGLES3::get_render_info(RS::RenderInfo p_info) {
-// switch (p_info) {
-// case RS::INFO_OBJECTS_IN_FRAME:
-// return info.render_final.object_count;
-// case RS::INFO_VERTICES_IN_FRAME:
-// return info.render_final.vertices_count;
-// case RS::INFO_MATERIAL_CHANGES_IN_FRAME:
-// return info.render_final.material_switch_count;
-// case RS::INFO_SHADER_CHANGES_IN_FRAME:
-// return info.render_final.shader_rebind_count;
-// case RS::INFO_SURFACE_CHANGES_IN_FRAME:
-// return info.render_final.surface_switch_count;
-// case RS::INFO_DRAW_CALLS_IN_FRAME:
-// return info.render_final.draw_call_count;
-// /*
-// case RS::INFO_2D_ITEMS_IN_FRAME:
-// return info.render_final._2d_item_count;
-// case RS::INFO_2D_DRAW_CALLS_IN_FRAME:
-// return info.render_final._2d_draw_call_count;
-//*/
-// case RS::INFO_USAGE_VIDEO_MEM_TOTAL:
-// return 0; //no idea
-// case RS::INFO_VIDEO_MEM_USED:
-// return info.vertex_mem + info.texture_mem;
-// case RS::INFO_TEXTURE_MEM_USED:
-// return info.texture_mem;
-// case RS::INFO_VERTEX_MEM_USED:
-// return info.vertex_mem;
-// default:
-// return 0; //no idea either
-// }
-//}
-
-String RasterizerStorageGLES3::get_video_adapter_name() const {
- return (const char *)glGetString(GL_RENDERER);
-}
-
-String RasterizerStorageGLES3::get_video_adapter_vendor() const {
- return (const char *)glGetString(GL_VENDOR);
-}
-
-RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() const {
- return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER;
-}
-
-String RasterizerStorageGLES3::get_video_adapter_api_version() const {
- return (const char *)glGetString(GL_VERSION);
-}
-
-void RasterizerStorageGLES3::initialize() {
- config = GLES3::Config::get_singleton();
-
- // skeleton buffer
- {
- resources.skeleton_transform_buffer_size = 0;
- glGenBuffers(1, &resources.skeleton_transform_buffer);
- }
-
- // radical inverse vdc cache texture
- // used for cubemap filtering
- glGenTextures(1, &resources.radical_inverse_vdc_cache_tex);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, resources.radical_inverse_vdc_cache_tex);
- /*
- uint8_t radical_inverse[512];
-
- for (uint32_t i = 0; i < 512; i++) {
- uint32_t bits = i;
-
- bits = (bits << 16) | (bits >> 16);
- bits = ((bits & 0x55555555) << 1) | ((bits & 0xAAAAAAAA) >> 1);
- bits = ((bits & 0x33333333) << 2) | ((bits & 0xCCCCCCCC) >> 2);
- bits = ((bits & 0x0F0F0F0F) << 4) | ((bits & 0xF0F0F0F0) >> 4);
- bits = ((bits & 0x00FF00FF) << 8) | ((bits & 0xFF00FF00) >> 8);
-
- float value = float(bits) * 2.3283064365386963e-10;
- radical_inverse[i] = uint8_t(CLAMP(value * 255.0, 0, 255));
- }
-
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 512, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, radical_inverse);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //need this for proper sampling
- */
- glBindTexture(GL_TEXTURE_2D, 0);
-
- {
- glGenFramebuffers(1, &resources.mipmap_blur_fbo);
- glGenTextures(1, &resources.mipmap_blur_color);
- }
-
-#ifdef GLES_OVER_GL
- glEnable(GL_PROGRAM_POINT_SIZE);
-#endif
-}
-
-void RasterizerStorageGLES3::finalize() {
-}
-
-void RasterizerStorageGLES3::update_memory_info() {
-}
-
-uint64_t RasterizerStorageGLES3::get_rendering_info(RS::RenderingInfo p_info) {
- return 0;
-}
-
-void RasterizerStorageGLES3::update_dirty_resources() {
- GLES3::MaterialStorage::get_singleton()->_update_global_variables();
- GLES3::MaterialStorage::get_singleton()->_update_queued_materials();
- //GLES3::MeshStorage::get_singleton()->_update_dirty_skeletons();
- GLES3::MeshStorage::get_singleton()->_update_dirty_multimeshes();
-}
-
-RasterizerStorageGLES3::RasterizerStorageGLES3() {
- initialize();
-}
-
-RasterizerStorageGLES3::~RasterizerStorageGLES3() {
-}
-
-#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
deleted file mode 100644
index c42efbce19..0000000000
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*************************************************************************/
-/* rasterizer_storage_gles3.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RASTERIZER_STORAGE_OPENGL_H
-#define RASTERIZER_STORAGE_OPENGL_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/local_vector.h"
-#include "core/templates/rid_owner.h"
-#include "core/templates/self_list.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_storage.h"
-#include "servers/rendering/shader_compiler.h"
-#include "servers/rendering/shader_language.h"
-#include "storage/config.h"
-#include "storage/light_storage.h"
-#include "storage/material_storage.h"
-#include "storage/mesh_storage.h"
-#include "storage/texture_storage.h"
-
-// class RasterizerCanvasGLES3;
-// class RasterizerSceneGLES3;
-
-class RasterizerStorageGLES3 : public RendererStorage {
-public:
- // RasterizerCanvasGLES3 *canvas;
- // RasterizerSceneGLES3 *scene;
-
- GLES3::Config *config = nullptr;
-
- static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.rows[0][0];
- p_array[1] = p_mtx.basis.rows[1][0];
- p_array[2] = p_mtx.basis.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.basis.rows[0][1];
- p_array[5] = p_mtx.basis.rows[1][1];
- p_array[6] = p_mtx.basis.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.basis.rows[0][2];
- p_array[9] = p_mtx.basis.rows[1][2];
- p_array[10] = p_mtx.basis.rows[2][2];
- p_array[11] = 0;
- p_array[12] = p_mtx.origin.x;
- p_array[13] = p_mtx.origin.y;
- p_array[14] = p_mtx.origin.z;
- p_array[15] = 1;
- }
-
- static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.rows[0][0];
- p_array[1] = p_mtx.rows[1][0];
- p_array[2] = p_mtx.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.rows[0][1];
- p_array[5] = p_mtx.rows[1][1];
- p_array[6] = p_mtx.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.rows[0][2];
- p_array[9] = p_mtx.rows[1][2];
- p_array[10] = p_mtx.rows[2][2];
- p_array[11] = 0;
- }
-
- static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
- }
-
- // Buffer size is specified in bytes
- static Vector<uint8_t> buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size);
-
- struct Resources {
- GLuint mipmap_blur_fbo;
- GLuint mipmap_blur_color;
-
- GLuint radical_inverse_vdc_cache_tex;
- bool use_rgba_2d_shadows;
-
- size_t skeleton_transform_buffer_size;
- GLuint skeleton_transform_buffer;
- LocalVector<float> skeleton_transform_cpu_buffer;
-
- } resources;
-
- struct Info {
- uint64_t texture_mem = 0;
- uint64_t vertex_mem = 0;
-
- struct Render {
- uint32_t object_count;
- uint32_t draw_call_count;
- uint32_t material_switch_count;
- uint32_t surface_switch_count;
- uint32_t shader_rebind_count;
- uint32_t vertices_count;
- uint32_t _2d_item_count;
- uint32_t _2d_draw_call_count;
-
- void reset() {
- object_count = 0;
- draw_call_count = 0;
- material_switch_count = 0;
- surface_switch_count = 0;
- shader_rebind_count = 0;
- vertices_count = 0;
- _2d_item_count = 0;
- _2d_draw_call_count = 0;
- }
- } render, render_final, snap;
-
- Info() {
- render.reset();
- render_final.reset();
- }
-
- } info;
-
- /////////////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////API////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////
-
-public:
- virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
-
- /* OCCLUDER */
-
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
-
- /* FOG VOLUMES */
-
- RID fog_volume_allocate() override;
- void fog_volume_initialize(RID p_rid) override;
-
- void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
- void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
- void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
- AABB fog_volume_get_aabb(RID p_fog_volume) const override;
- RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
-
- /* VISIBILITY NOTIFIER */
- RID visibility_notifier_allocate() override;
- void visibility_notifier_initialize(RID p_notifier) override;
- void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override;
- void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override;
-
- AABB visibility_notifier_get_aabb(RID p_notifier) const override;
- void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
-
- // access from canvas
- // GLES3::RenderTarget * render_target_get(RID p_render_target);
-
- /* CANVAS SHADOW */
-
- struct CanvasLightShadow {
- RID self;
- int size;
- int height;
- GLuint fbo;
- GLuint depth;
- GLuint distance; //for older devices
- };
-
- RID_PtrOwner<CanvasLightShadow> canvas_light_shadow_owner;
-
- RID canvas_light_shadow_buffer_create(int p_width);
-
- /* LIGHT SHADOW MAPPING */
- /*
- struct CanvasOccluder {
- RID self;
-
- GLuint vertex_id; // 0 means, unconfigured
- GLuint index_id; // 0 means, unconfigured
- LocalVector<Vector2> lines;
- int len;
- };
-
- RID_Owner<CanvasOccluder> canvas_occluder_owner;
-
- RID canvas_light_occluder_create();
- void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines);
-*/
-
- RS::InstanceType get_base_type(RID p_rid) const override;
-
- bool free(RID p_rid) override;
-
- void initialize();
- void finalize();
-
- void update_memory_info() override;
- uint64_t get_rendering_info(RS::RenderingInfo p_info) override;
-
- bool has_os_feature(const String &p_feature) const override;
-
- void update_dirty_resources() override;
-
- void set_debug_generate_wireframes(bool p_generate) override;
-
- // void render_info_begin_capture() override;
- // void render_info_end_capture() override;
- // int get_captured_render_info(RS::RenderInfo p_info) override;
-
- // int get_render_info(RS::RenderInfo p_info) override;
- String get_video_adapter_name() const override;
- String get_video_adapter_vendor() const override;
- RenderingDevice::DeviceType get_video_adapter_type() const override;
- String get_video_adapter_api_version() const override;
-
- void capture_timestamps_begin() override {}
- void capture_timestamp(const String &p_name) override {}
- uint32_t get_captured_timestamps_count() const override {
- return 0;
- }
- uint64_t get_captured_timestamps_frame() const override {
- return 0;
- }
- uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override {
- return 0;
- }
- uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override {
- return 0;
- }
- String get_captured_timestamp_name(uint32_t p_index) const override {
- return String();
- }
-
- RasterizerStorageGLES3();
- ~RasterizerStorageGLES3();
-};
-
-#endif // GLES3_ENABLED
-
-#endif // RASTERIZER_STORAGE_OPENGL_H
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index d8dd573f57..83ffe8b1e1 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -10,7 +10,7 @@ if "GLES3_GLSL" in env["BUILDERS"]:
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#gles3_builders.py"])
env.GLES3_GLSL("canvas.glsl")
env.GLES3_GLSL("copy.glsl")
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 954aa11c0d..22578c9e91 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -139,12 +139,12 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
} break;
case RS::LIGHT_PARAM_SIZE: {
if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
//changing from no size to size and the opposite
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
} break;
default: {
@@ -160,7 +160,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_projector(RID p_light, RID p_texture) {
@@ -182,7 +182,7 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
if (light->projector.is_valid()) {
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
}
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
}
@@ -200,7 +200,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
@@ -220,7 +220,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->reverse_cull = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@@ -230,7 +230,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod
light->bake_mode = p_bake_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@@ -240,7 +240,7 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo
light->omni_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
@@ -256,7 +256,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec
light->directional_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@@ -265,7 +265,7 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable
light->directional_blend_splits = p_enable;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
@@ -476,4 +476,104 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
return 0;
}
+/* LIGHT SHADOW MAPPING */
+/*
+
+RID LightStorage::canvas_light_occluder_create() {
+ CanvasOccluder *co = memnew(CanvasOccluder);
+ co->index_id = 0;
+ co->vertex_id = 0;
+ co->len = 0;
+
+ return canvas_occluder_owner.make_rid(co);
+}
+
+void LightStorage::canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2> &p_lines) {
+ CanvasOccluder *co = canvas_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!co);
+
+ co->lines = p_lines;
+
+ if (p_lines.size() != co->len) {
+ if (co->index_id) {
+ glDeleteBuffers(1, &co->index_id);
+ } if (co->vertex_id) {
+ glDeleteBuffers(1, &co->vertex_id);
+ }
+
+ co->index_id = 0;
+ co->vertex_id = 0;
+ co->len = 0;
+ }
+
+ if (p_lines.size()) {
+ PoolVector<float> geometry;
+ PoolVector<uint16_t> indices;
+ int lc = p_lines.size();
+
+ geometry.resize(lc * 6);
+ indices.resize(lc * 3);
+
+ PoolVector<float>::Write vw = geometry.write();
+ PoolVector<uint16_t>::Write iw = indices.write();
+
+ PoolVector<Vector2>::Read lr = p_lines.read();
+
+ const int POLY_HEIGHT = 16384;
+
+ for (int i = 0; i < lc / 2; i++) {
+ vw[i * 12 + 0] = lr[i * 2 + 0].x;
+ vw[i * 12 + 1] = lr[i * 2 + 0].y;
+ vw[i * 12 + 2] = POLY_HEIGHT;
+
+ vw[i * 12 + 3] = lr[i * 2 + 1].x;
+ vw[i * 12 + 4] = lr[i * 2 + 1].y;
+ vw[i * 12 + 5] = POLY_HEIGHT;
+
+ vw[i * 12 + 6] = lr[i * 2 + 1].x;
+ vw[i * 12 + 7] = lr[i * 2 + 1].y;
+ vw[i * 12 + 8] = -POLY_HEIGHT;
+
+ vw[i * 12 + 9] = lr[i * 2 + 0].x;
+ vw[i * 12 + 10] = lr[i * 2 + 0].y;
+ vw[i * 12 + 11] = -POLY_HEIGHT;
+
+ iw[i * 6 + 0] = i * 4 + 0;
+ iw[i * 6 + 1] = i * 4 + 1;
+ iw[i * 6 + 2] = i * 4 + 2;
+
+ iw[i * 6 + 3] = i * 4 + 2;
+ iw[i * 6 + 4] = i * 4 + 3;
+ iw[i * 6 + 5] = i * 4 + 0;
+ }
+
+ //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
+
+ if (!co->vertex_id) {
+ glGenBuffers(1, &co->vertex_id);
+ glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
+ glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW);
+ } else {
+ glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, lc * 6 * sizeof(real_t), vw.ptr());
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+
+ if (!co->index_id) {
+ glGenBuffers(1, &co->index_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW);
+ } else {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, lc * 3 * sizeof(uint16_t), iw.ptr());
+ }
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
+
+ co->len = lc;
+ }
+}
+*/
+
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index 5acaf45aa3..575ab93eab 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -37,8 +37,8 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/light_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "platform_config.h"
#ifndef OPENGL_INCLUDE_H
@@ -72,7 +72,7 @@ struct Light {
RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
uint64_t version = 0;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* REFLECTION PROBE */
@@ -93,7 +93,7 @@ struct ReflectionProbe {
uint32_t cull_mask = (1 << 20) - 1;
float mesh_lod_threshold = 0.01;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* LIGHTMAP */
@@ -115,7 +115,7 @@ struct Lightmap {
int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
};
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
class LightStorage : public RendererLightStorage {
@@ -321,6 +321,23 @@ public:
virtual bool lightmap_is_interior(RID p_lightmap) const override;
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
virtual float lightmap_get_probe_capture_update_speed() const override;
+
+ /* LIGHT SHADOW MAPPING */
+ /*
+ struct CanvasOccluder {
+ RID self;
+
+ GLuint vertex_id; // 0 means, unconfigured
+ GLuint index_id; // 0 means, unconfigured
+ LocalVector<Vector2> lines;
+ int len;
+ };
+
+ RID_Owner<CanvasOccluder> canvas_occluder_owner;
+
+ RID canvas_light_occluder_create();
+ void canvas_light_occluder_set_polylines(RID p_occluder, const LocalVector<Vector2> &p_lines);
+ */
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index fd50bdedbd..aa19826953 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -2456,7 +2456,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
for (Material *E : shader->owners) {
Material *material = E;
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
}
@@ -2593,7 +2593,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
}
if (p_shader.is_null()) {
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
material->shader_id = 0;
return;
}
@@ -2616,7 +2616,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
@@ -2662,7 +2662,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material
material->data->set_next_pass(p_next_material);
}
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
@@ -2715,7 +2715,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li
}
}
-void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
p_instance->update_dependency(&material->dependency);
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 09f6680bec..6ad277c2b9 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -37,10 +37,10 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "../shaders/canvas.glsl.gen.h"
#include "../shaders/cubemap_filter.glsl.gen.h"
@@ -125,7 +125,7 @@ struct Material {
RID next_pass;
SelfList<Material> update_element;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
Material() :
update_element(this) {}
@@ -453,6 +453,48 @@ public:
MaterialStorage();
virtual ~MaterialStorage();
+ static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[1][0];
+ p_array[2] = p_mtx.basis.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.basis.rows[0][1];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.basis.rows[0][2];
+ p_array[9] = p_mtx.basis.rows[1][2];
+ p_array[10] = p_mtx.basis.rows[2][2];
+ p_array[11] = 0;
+ p_array[12] = p_mtx.origin.x;
+ p_array[13] = p_mtx.origin.y;
+ p_array[14] = p_mtx.origin.z;
+ p_array[15] = 1;
+ }
+
+ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
+ p_array[11] = 0;
+ }
+
+ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ }
+ }
+ }
+
struct Shaders {
CanvasShaderGLES3 canvas_shader;
SkyShaderGLES3 sky_shader;
@@ -534,7 +576,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
Material *material = material_owner.get_or_null(p_material);
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 5aa82bfcc1..88b81805fa 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -31,8 +31,8 @@
#ifdef GLES3_ENABLED
#include "mesh_storage.h"
-#include "../rasterizer_storage_gles3.h"
#include "material_storage.h"
+#include "utilities.h"
using namespace GLES3;
@@ -64,6 +64,8 @@ void MeshStorage::mesh_free(RID p_rid) {
mesh_clear(p_rid);
mesh_set_shadow_mesh(p_rid, RID());
Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!mesh);
+
mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
@@ -72,7 +74,7 @@ void MeshStorage::mesh_free(RID p_rid) {
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
mesh_owner.free(p_rid);
@@ -268,12 +270,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
mesh->material_cache.clear();
@@ -314,7 +316,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear();
}
@@ -335,10 +337,10 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- sd.vertex_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
+ sd.vertex_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.vertex_buffer, s.vertex_buffer_size);
if (s.attribute_buffer != 0) {
- sd.attribute_data = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size);
+ sd.attribute_data = Utilities::buffer_get_data(GL_ARRAY_BUFFER, s.attribute_buffer, s.attribute_buffer_size);
}
sd.vertex_count = s.vertex_count;
@@ -346,14 +348,14 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
sd.primitive = s.primitive;
if (sd.index_count) {
- sd.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer, s.index_buffer_size);
+ sd.index_data = Utilities::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer, s.index_buffer_size);
}
sd.aabb = s.aabb;
for (uint32_t i = 0; i < s.lod_count; i++) {
RS::SurfaceData::LOD lod;
lod.edge_length = s.lods[i].edge_length;
- lod.index_data = RasterizerStorageGLES3::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.lods[i].index_buffer, s.lods[i].index_buffer_size);
+ lod.index_data = Utilities::buffer_get_data(GL_ELEMENT_ARRAY_BUFFER, s.lods[i].index_buffer, s.lods[i].index_buffer_size);
sd.lods.push_back(lod);
}
@@ -504,7 +506,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
shadow_mesh->shadow_owners.insert(mesh);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
void MeshStorage::mesh_clear(RID p_mesh) {
@@ -553,12 +555,12 @@ void MeshStorage::mesh_clear(RID p_mesh) {
_mesh_instance_clear(mi);
}
mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
@@ -899,7 +901,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}
int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
@@ -926,14 +928,14 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
} else if (multimesh->instances) {
// Need to re-create AABB. Unfortunately, calling this has a penalty.
if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
+ Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
const uint8_t *r = buffer.ptr();
const float *data = (const float *)r;
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
}
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
@@ -950,7 +952,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
float *w = multimesh->data_cache.ptrw();
if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
+ Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
{
const uint8_t *r = buffer.ptr();
@@ -1348,7 +1350,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
const float *data = multimesh->data_cache.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1363,7 +1365,7 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
} else {
// Buffer not cached, so fetch from GPU memory. This can be a stalling operation, avoid whenever possible.
- Vector<uint8_t> buffer = RasterizerStorageGLES3::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
+ Vector<uint8_t> buffer = Utilities::buffer_get_data(GL_ARRAY_BUFFER, multimesh->buffer, multimesh->instances * multimesh->stride_cache * sizeof(float));
ret.resize(multimesh->instances * multimesh->stride_cache);
{
float *w = ret.ptrw();
@@ -1439,7 +1441,7 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
multimesh->visible_instances = p_visible;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
@@ -1493,7 +1495,7 @@ void MeshStorage::_update_dirty_multimeshes() {
if (multimesh->aabb_dirty && multimesh->mesh.is_valid()) {
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1542,7 +1544,12 @@ Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bo
return Transform2D();
}
-void MeshStorage::skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) {
+void MeshStorage::skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) {
+}
+
+/* OCCLUDER */
+
+void MeshStorage::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 3bb7061413..c51cd5dcd6 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -37,6 +37,7 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "platform_config.h"
#ifndef OPENGL_INCLUDE_H
@@ -126,7 +127,7 @@ struct Mesh {
RID shadow_mesh;
HashSet<Mesh *> shadow_owners;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* Mesh Instance */
@@ -179,7 +180,7 @@ struct MultiMesh {
bool dirty = false;
MultiMesh *dirty_list = nullptr;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
struct Skeleton {
@@ -194,7 +195,7 @@ struct Skeleton {
uint64_t version = 1;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
class MeshStorage : public RendererMeshStorage {
@@ -531,7 +532,11 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
- virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
+ /* OCCLUDER */
+
+ void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 42c80da39a..c05f516548 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -183,6 +183,12 @@ TextureStorage::TextureStorage() {
texture.gl_set_filter(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
}
}
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+#ifdef GLES_OVER_GL
+ glEnable(GL_PROGRAM_POINT_SIZE);
+#endif
}
TextureStorage::~TextureStorage() {
@@ -244,6 +250,55 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
ct->texture_repeat = p_repeat;
}
+/* CANVAS SHADOW */
+
+RID TextureStorage::canvas_light_shadow_buffer_create(int p_width) {
+ Config *config = Config::get_singleton();
+ CanvasLightShadow *cls = memnew(CanvasLightShadow);
+
+ if (p_width > config->max_texture_size) {
+ p_width = config->max_texture_size;
+ }
+
+ cls->size = p_width;
+ cls->height = 16;
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenFramebuffers(1, &cls->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
+
+ glGenRenderbuffers(1, &cls->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
+
+ glGenTextures(1, &cls->distance);
+ glBindTexture(GL_TEXTURE_2D, cls->distance);
+ if (config->use_rgba_2d_shadows) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, nullptr);
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls->distance, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ //printf("errnum: %x\n",status);
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ memdelete(cls);
+ ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
+ }
+
+ return canvas_light_shadow_owner.make_rid(cls);
+}
+
/* Texture API */
Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index d6d04e45a1..de887f9184 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -132,6 +132,17 @@ struct CanvasTexture {
bool cleared_cache = true;
};
+/* CANVAS SHADOW */
+
+struct CanvasLightShadow {
+ RID self;
+ int size;
+ int height;
+ GLuint fbo;
+ GLuint depth;
+ GLuint distance; //for older devices
+};
+
struct RenderTarget;
struct Texture {
@@ -364,6 +375,10 @@ private:
RID_Owner<CanvasTexture, true> canvas_texture_owner;
+ /* CANVAS SHADOW */
+
+ RID_PtrOwner<CanvasLightShadow> canvas_light_shadow_owner;
+
/* Texture API */
mutable RID_Owner<Texture> texture_owner;
@@ -403,6 +418,10 @@ public:
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+ /* CANVAS SHADOW */
+
+ RID canvas_light_shadow_buffer_create(int p_width);
+
/* Texture API */
Texture *get_texture(RID p_rid) {
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
new file mode 100644
index 0000000000..a00210a2ab
--- /dev/null
+++ b/drivers/gles3/storage/utilities.cpp
@@ -0,0 +1,353 @@
+/*************************************************************************/
+/* utilities.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "utilities.h"
+#include "config.h"
+#include "light_storage.h"
+#include "material_storage.h"
+#include "mesh_storage.h"
+#include "particles_storage.h"
+#include "texture_storage.h"
+
+using namespace GLES3;
+
+Utilities *Utilities::singleton = nullptr;
+
+Utilities::Utilities() {
+ singleton = this;
+}
+
+Utilities::~Utilities() {
+ singleton = nullptr;
+}
+
+Vector<uint8_t> Utilities::buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size) {
+ Vector<uint8_t> ret;
+ ret.resize(p_buffer_size);
+ glBindBuffer(p_target, p_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(p_target, 0, p_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(p_target, 0, p_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, Vector<uint8_t>());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, p_buffer_size);
+ }
+ glUnmapBuffer(p_target);
+#endif
+ glBindBuffer(p_target, 0);
+ return ret;
+}
+
+/* INSTANCES */
+
+RS::InstanceType Utilities::get_base_type(RID p_rid) const {
+ if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ return RS::INSTANCE_MESH;
+ } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ return RS::INSTANCE_MULTIMESH;
+ } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
+ return RS::INSTANCE_LIGHT;
+ }
+ return RS::INSTANCE_NONE;
+}
+
+bool Utilities::free(RID p_rid) {
+ if (GLES3::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->render_target_free(p_rid);
+ return true;
+ } else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->texture_free(p_rid);
+ return true;
+ } else if (GLES3::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
+ return true;
+ } else if (GLES3::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
+ GLES3::MaterialStorage::get_singleton()->shader_free(p_rid);
+ return true;
+ } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
+ GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
+ return true;
+ } else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ GLES3::MeshStorage::get_singleton()->mesh_free(p_rid);
+ return true;
+ } else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid);
+ return true;
+ } else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
+ GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
+ return true;
+ } else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
+ GLES3::LightStorage::get_singleton()->light_free(p_rid);
+ return true;
+ } else {
+ return false;
+ }
+ /*
+ else if (reflection_probe_owner.owns(p_rid)) {
+ // delete the texture
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
+ reflection_probe->instance_remove_deps();
+
+ reflection_probe_owner.free(p_rid);
+ memdelete(reflection_probe);
+
+ return true;
+ } else if (lightmap_capture_data_owner.owns(p_rid)) {
+ // delete the texture
+ LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get_or_null(p_rid);
+ lightmap_capture->instance_remove_deps();
+
+ lightmap_capture_data_owner.free(p_rid);
+ memdelete(lightmap_capture);
+ return true;
+
+ } else if (canvas_occluder_owner.owns(p_rid)) {
+ CanvasOccluder *co = canvas_occluder_owner.get_or_null(p_rid);
+ if (co->index_id) {
+ glDeleteBuffers(1, &co->index_id);
+ }
+ if (co->vertex_id) {
+ glDeleteBuffers(1, &co->vertex_id);
+ }
+
+ canvas_occluder_owner.free(p_rid);
+ memdelete(co);
+
+ return true;
+
+ } else if (canvas_light_shadow_owner.owns(p_rid)) {
+ CanvasLightShadow *cls = canvas_light_shadow_owner.get_or_null(p_rid);
+ glDeleteFramebuffers(1, &cls->fbo);
+ glDeleteRenderbuffers(1, &cls->depth);
+ glDeleteTextures(1, &cls->distance);
+ canvas_light_shadow_owner.free(p_rid);
+ memdelete(cls);
+
+ return true;
+ }
+ */
+}
+
+/* DEPENDENCIES */
+
+void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
+ if (MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base);
+ p_instance->update_dependency(&mesh->dependency);
+ } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base);
+ p_instance->update_dependency(&multimesh->dependency);
+ if (multimesh->mesh.is_valid()) {
+ base_update_dependency(multimesh->mesh, p_instance);
+ }
+ } else if (LightStorage::get_singleton()->owns_light(p_base)) {
+ Light *l = LightStorage::get_singleton()->get_light(p_base);
+ p_instance->update_dependency(&l->dependency);
+ }
+}
+
+/* VISIBILITY NOTIFIER */
+
+RID Utilities::visibility_notifier_allocate() {
+ return RID();
+}
+
+void Utilities::visibility_notifier_initialize(RID p_notifier) {
+}
+
+void Utilities::visibility_notifier_free(RID p_notifier) {
+}
+
+void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
+}
+
+void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
+}
+
+AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const {
+ return AABB();
+}
+
+void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
+}
+
+/* TIMING */
+
+//void Utilities::render_info_begin_capture() {
+// info.snap = info.render;
+//}
+
+//void Utilities::render_info_end_capture() {
+// info.snap.object_count = info.render.object_count - info.snap.object_count;
+// info.snap.draw_call_count = info.render.draw_call_count - info.snap.draw_call_count;
+// info.snap.material_switch_count = info.render.material_switch_count - info.snap.material_switch_count;
+// info.snap.surface_switch_count = info.render.surface_switch_count - info.snap.surface_switch_count;
+// info.snap.shader_rebind_count = info.render.shader_rebind_count - info.snap.shader_rebind_count;
+// info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count;
+// info.snap._2d_item_count = info.render._2d_item_count - info.snap._2d_item_count;
+// info.snap._2d_draw_call_count = info.render._2d_draw_call_count - info.snap._2d_draw_call_count;
+//}
+
+//int Utilities::get_captured_render_info(RS::RenderInfo p_info) {
+// switch (p_info) {
+// case RS::INFO_OBJECTS_IN_FRAME: {
+// return info.snap.object_count;
+// } break;
+// case RS::INFO_VERTICES_IN_FRAME: {
+// return info.snap.vertices_count;
+// } break;
+// case RS::INFO_MATERIAL_CHANGES_IN_FRAME: {
+// return info.snap.material_switch_count;
+// } break;
+// case RS::INFO_SHADER_CHANGES_IN_FRAME: {
+// return info.snap.shader_rebind_count;
+// } break;
+// case RS::INFO_SURFACE_CHANGES_IN_FRAME: {
+// return info.snap.surface_switch_count;
+// } break;
+// case RS::INFO_DRAW_CALLS_IN_FRAME: {
+// return info.snap.draw_call_count;
+// } break;
+// /*
+// case RS::INFO_2D_ITEMS_IN_FRAME: {
+// return info.snap._2d_item_count;
+// } break;
+// case RS::INFO_2D_DRAW_CALLS_IN_FRAME: {
+// return info.snap._2d_draw_call_count;
+// } break;
+// */
+// default: {
+// return get_render_info(p_info);
+// }
+// }
+//}
+
+//int Utilities::get_render_info(RS::RenderInfo p_info) {
+// switch (p_info) {
+// case RS::INFO_OBJECTS_IN_FRAME:
+// return info.render_final.object_count;
+// case RS::INFO_VERTICES_IN_FRAME:
+// return info.render_final.vertices_count;
+// case RS::INFO_MATERIAL_CHANGES_IN_FRAME:
+// return info.render_final.material_switch_count;
+// case RS::INFO_SHADER_CHANGES_IN_FRAME:
+// return info.render_final.shader_rebind_count;
+// case RS::INFO_SURFACE_CHANGES_IN_FRAME:
+// return info.render_final.surface_switch_count;
+// case RS::INFO_DRAW_CALLS_IN_FRAME:
+// return info.render_final.draw_call_count;
+// /*
+// case RS::INFO_2D_ITEMS_IN_FRAME:
+// return info.render_final._2d_item_count;
+// case RS::INFO_2D_DRAW_CALLS_IN_FRAME:
+// return info.render_final._2d_draw_call_count;
+//*/
+// case RS::INFO_USAGE_VIDEO_MEM_TOTAL:
+// return 0; //no idea
+// case RS::INFO_VIDEO_MEM_USED:
+// return info.vertex_mem + info.texture_mem;
+// case RS::INFO_TEXTURE_MEM_USED:
+// return info.texture_mem;
+// case RS::INFO_VERTEX_MEM_USED:
+// return info.vertex_mem;
+// default:
+// return 0; //no idea either
+// }
+//}
+
+/* MISC */
+
+void Utilities::update_dirty_resources() {
+ MaterialStorage::get_singleton()->_update_global_variables();
+ MaterialStorage::get_singleton()->_update_queued_materials();
+ //MeshStorage::get_singleton()->_update_dirty_skeletons();
+ MeshStorage::get_singleton()->_update_dirty_multimeshes();
+}
+
+void Utilities::set_debug_generate_wireframes(bool p_generate) {
+}
+
+bool Utilities::has_os_feature(const String &p_feature) const {
+ Config *config = Config::get_singleton();
+ if (!config) {
+ return false;
+ }
+
+ if (p_feature == "rgtc") {
+ return config->rgtc_supported;
+ }
+
+ if (p_feature == "s3tc") {
+ return config->s3tc_supported;
+ }
+
+ if (p_feature == "bptc") {
+ return config->bptc_supported;
+ }
+
+ if (p_feature == "etc" || p_feature == "etc2") {
+ return config->etc2_supported;
+ }
+
+ return false;
+}
+
+void Utilities::update_memory_info() {
+}
+
+uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
+ return 0;
+}
+
+String Utilities::get_video_adapter_name() const {
+ return (const char *)glGetString(GL_RENDERER);
+}
+
+String Utilities::get_video_adapter_vendor() const {
+ return (const char *)glGetString(GL_VENDOR);
+}
+
+RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
+ return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER;
+}
+
+String Utilities::get_video_adapter_api_version() const {
+ return (const char *)glGetString(GL_VERSION);
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/utilities.h b/drivers/gles3/storage/utilities.h
new file mode 100644
index 0000000000..523033886c
--- /dev/null
+++ b/drivers/gles3/storage/utilities.h
@@ -0,0 +1,159 @@
+/*************************************************************************/
+/* utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef UTILITIES_GLES3_H
+#define UTILITIES_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "servers/rendering/storage/utilities.h"
+
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
+namespace GLES3 {
+
+class Utilities : public RendererUtilities {
+private:
+ static Utilities *singleton;
+
+public:
+ static Utilities *get_singleton() { return singleton; }
+
+ Utilities();
+ ~Utilities();
+
+ // Buffer size is specified in bytes
+ static Vector<uint8_t> buffer_get_data(GLenum p_target, GLuint p_buffer, uint32_t p_buffer_size);
+
+ /* INSTANCES */
+
+ virtual RS::InstanceType get_base_type(RID p_rid) const override;
+ virtual bool free(RID p_rid) override;
+
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
+ /* VISIBILITY NOTIFIER */
+ virtual RID visibility_notifier_allocate() override;
+ virtual void visibility_notifier_initialize(RID p_notifier) override;
+ virtual void visibility_notifier_free(RID p_notifier) override;
+
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
+
+ /* TIMING */
+
+ struct Info {
+ uint64_t texture_mem = 0;
+ uint64_t vertex_mem = 0;
+
+ struct Render {
+ uint32_t object_count;
+ uint32_t draw_call_count;
+ uint32_t material_switch_count;
+ uint32_t surface_switch_count;
+ uint32_t shader_rebind_count;
+ uint32_t vertices_count;
+ uint32_t _2d_item_count;
+ uint32_t _2d_draw_call_count;
+
+ void reset() {
+ object_count = 0;
+ draw_call_count = 0;
+ material_switch_count = 0;
+ surface_switch_count = 0;
+ shader_rebind_count = 0;
+ vertices_count = 0;
+ _2d_item_count = 0;
+ _2d_draw_call_count = 0;
+ }
+ } render, render_final, snap;
+
+ Info() {
+ render.reset();
+ render_final.reset();
+ }
+
+ } info;
+
+ virtual void capture_timestamps_begin() override {}
+ virtual void capture_timestamp(const String &p_name) override {}
+ virtual uint32_t get_captured_timestamps_count() const override {
+ return 0;
+ }
+ virtual uint64_t get_captured_timestamps_frame() const override {
+ return 0;
+ }
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override {
+ return 0;
+ }
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override {
+ return 0;
+ }
+ virtual String get_captured_timestamp_name(uint32_t p_index) const override {
+ return String();
+ }
+
+ // void render_info_begin_capture() override;
+ // void render_info_end_capture() override;
+ // int get_captured_render_info(RS::RenderInfo p_info) override;
+
+ // int get_render_info(RS::RenderInfo p_info) override;
+
+ /* MISC */
+
+ virtual void update_dirty_resources() override;
+ virtual void set_debug_generate_wireframes(bool p_generate) override;
+
+ virtual bool has_os_feature(const String &p_feature) const override;
+
+ virtual void update_memory_info() override;
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override;
+ virtual String get_video_adapter_name() const override;
+ virtual String get_video_adapter_vendor() const override;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
+ virtual String get_video_adapter_api_version() const override;
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !UTILITIES_GLES3_H
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 7e6105f033..39dbadf3cd 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -33,6 +33,7 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
#include "core/os/memory.h"
+#include "core/os/os.h"
#include "core/string/print_string.h"
#include "core/templates/list.h"
@@ -49,10 +50,6 @@
#include <mntent.h>
#endif
-Ref<DirAccess> DirAccessUnix::create_fs() {
- return memnew(DirAccessUnix);
-}
-
Error DirAccessUnix::list_dir_begin() {
list_dir_end(); //close any previous dir opening!
@@ -216,10 +213,11 @@ static bool _filter_drive(struct mntent *mnt) {
#endif
static void _get_drives(List<String> *list) {
+ // Add root.
list->push_back("/");
#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
- // Check /etc/mtab for the list of mounted partitions
+ // Check /etc/mtab for the list of mounted partitions.
FILE *mtab = setmntent("/etc/mtab", "r");
if (mtab) {
struct mntent mnt;
@@ -239,7 +237,7 @@ static void _get_drives(List<String> *list) {
}
#endif
- // Add $HOME
+ // Add $HOME.
const char *home = getenv("HOME");
if (home) {
// Only add if it's not a duplicate
@@ -248,7 +246,8 @@ static void _get_drives(List<String> *list) {
list->push_back(home_name);
}
- // Check $HOME/.config/gtk-3.0/bookmarks
+ // Check GTK+3 bookmarks for both XDG locations (Documents, Downloads, etc.)
+ // and potential user-defined bookmarks.
char path[1024];
snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home);
FILE *fd = fopen(path, "r");
@@ -257,7 +256,7 @@ static void _get_drives(List<String> *list) {
while (fgets(string, 1024, fd)) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
- // Strip any unwanted edges on the strings and push_back if it's not a duplicate
+ // Strip any unwanted edges on the strings and push_back if it's not a duplicate.
String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
@@ -267,6 +266,12 @@ static void _get_drives(List<String> *list) {
fclose(fd);
}
+
+ // Add Desktop dir.
+ String dpath = OS::get_singleton()->get_system_dir(OS::SystemDir::SYSTEM_DIR_DESKTOP);
+ if (dpath.length() > 0 && !list->find(dpath)) {
+ list->push_back(dpath);
+ }
}
list->sort();
@@ -338,7 +343,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
String prev_dir;
char real_current_dir_name[2048];
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
- if (prev_dir.parse_utf8(real_current_dir_name)) {
+ if (prev_dir.parse_utf8(real_current_dir_name) != OK) {
prev_dir = real_current_dir_name; //no utf8, maybe latin?
}
@@ -500,7 +505,7 @@ DirAccessUnix::DirAccessUnix() {
// set current directory to an absolute path of the current directory
char real_current_dir_name[2048];
ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr);
- if (current_dir.parse_utf8(real_current_dir_name)) {
+ if (current_dir.parse_utf8(real_current_dir_name) != OK) {
current_dir = real_current_dir_name;
}
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 69530de337..5e2129b74a 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -43,13 +43,11 @@
class DirAccessUnix : public DirAccess {
DIR *dir_stream = nullptr;
- static Ref<DirAccess> create_fs();
-
- String current_dir;
bool _cisdir = false;
bool _cishidden = false;
protected:
+ String current_dir;
virtual String fix_unicode_name(const char *p_name) const { return String::utf8(p_name); }
virtual bool is_hidden(const String &p_name);
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index e0b2994b63..99836b7bea 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -333,10 +333,6 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
return FAILED;
}
-Ref<FileAccess> FileAccessUnix::create_libc() {
- return memnew(FileAccessUnix);
-}
-
CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr;
FileAccessUnix::~FileAccessUnix() {
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 4340bbbc82..0261b8be53 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -49,7 +49,6 @@ class FileAccessUnix : public FileAccess {
String path;
String path_src;
- static Ref<FileAccess> create_libc();
void _close();
public:
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 52a4d538e1..091287c652 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -313,7 +313,12 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
if (p_pipe_mutex) {
p_pipe_mutex->lock();
}
- (*r_pipe) += String::utf8(buf);
+ String pipe_out;
+ if (pipe_out.parse_utf8(buf) == OK) {
+ (*r_pipe) += pipe_out;
+ } else {
+ (*r_pipe) += String(buf); // If not valid UTF-8 try decode as Latin-1
+ }
if (p_pipe_mutex) {
p_pipe_mutex->unlock();
}
diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp
index 0301f5b7fa..2bf173a398 100644
--- a/drivers/vulkan/vulkan_context.cpp
+++ b/drivers/vulkan/vulkan_context.cpp
@@ -72,20 +72,20 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_messenger_callback(
strstr(pCallbackData->pMessage, "must be a memory object") != nullptr) {
return VK_FALSE;
}
- /*
- // This is a valid warning because its illegal in Vulkan, but in practice it should work according to VK_KHR_maintenance2
- if (strstr(pCallbackData->pMessage, "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) {
- return VK_FALSE;
- }
- if (strstr(pCallbackData->pMessage, "VK_FORMAT_R4G4B4A4_UNORM_PACK16 with tiling VK_IMAGE_TILING_OPTIMAL does not support usage that includes VK_IMAGE_USAGE_STORAGE_BIT") != nullptr) {
- return VK_FALSE;
- }
-*/
// Workaround for Vulkan-Loader usability bug: https://github.com/KhronosGroup/Vulkan-Loader/issues/262.
if (strstr(pCallbackData->pMessage, "wrong ELF class: ELFCLASS32") != nullptr) {
return VK_FALSE;
}
+
+#ifdef WINDOWS_ENABLED
+ // Some software installs Vulkan overlays in Windows registry and never cleans them up on uninstall.
+ // So we get spammy error level messages from the loader about those - make them verbose instead.
+ if (strstr(pCallbackData->pMessage, "loader_get_json: Failed to open JSON file") != nullptr) {
+ messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ }
+#endif
+
if (pCallbackData->pMessageIdName && strstr(pCallbackData->pMessageIdName, "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw") != nullptr) {
return VK_FALSE;
}
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index e612130041..500a3df127 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1577,10 +1577,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
int decimals = 2;
bool step_found = false;
- const float period_width = font->get_char_size('.', 0, font_size).width;
- float max_digit_width = font->get_char_size('0', 0, font_size).width;
+ const float period_width = font->get_char_size('.', font_size).width;
+ float max_digit_width = font->get_char_size('0', font_size).width;
for (int i = 1; i <= 9; i++) {
- const float digit_width = font->get_char_size('0' + i, 0, font_size).width;
+ const float digit_width = font->get_char_size('0' + i, font_size).width;
max_digit_width = MAX(digit_width, max_digit_width);
}
const int max_sc = int(Math::ceil(zoomw / scale));
@@ -1628,7 +1628,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
- prev_frame_ofs = i + font->get_string_size(itos(frame), font_size).x + 5 * EDSCALE;
+ prev_frame_ofs = i + font->get_string_size(itos(frame), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + 5 * EDSCALE;
}
}
}
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 272de725c8..50abe8bc36 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1636,30 +1636,35 @@ void CodeTextEditor::_apply_settings_change() {
_update_text_editor_theme();
font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
-
int ot_mode = EditorSettings::get_singleton()->get("interface/editor/code_font_contextual_ligatures");
- switch (ot_mode) {
- case 1: { // Disable ligatures.
- text_editor->clear_opentype_features();
- text_editor->set_opentype_feature("calt", 0);
- } break;
- case 2: { // Custom.
- text_editor->clear_opentype_features();
- Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
- Dictionary ftrs;
- for (int i = 0; i < subtag.size(); i++) {
- Vector<String> subtag_a = subtag[i].split("=");
- if (subtag_a.size() == 2) {
- text_editor->set_opentype_feature(subtag_a[0], subtag_a[1].to_int());
- } else if (subtag_a.size() == 1) {
- text_editor->set_opentype_feature(subtag_a[0], 1);
+
+ Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
+ if (fc.is_valid()) {
+ switch (ot_mode) {
+ case 1: { // Disable ligatures.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 0;
+ fc->set_opentype_features(ftrs);
+ } break;
+ case 2: { // Custom.
+ Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
+ Dictionary ftrs;
+ for (int i = 0; i < subtag.size(); i++) {
+ Vector<String> subtag_a = subtag[i].split("=");
+ if (subtag_a.size() == 2) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
+ } else if (subtag_a.size() == 1) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = 1;
+ }
}
- }
- } break;
- default: { // Default.
- text_editor->clear_opentype_features();
- text_editor->set_opentype_feature("calt", 1);
- } break;
+ fc->set_opentype_features(ftrs);
+ } break;
+ default: { // Default.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 1;
+ fc->set_opentype_features(ftrs);
+ } break;
+ }
}
text_editor->set_code_hint_draw_below(EDITOR_GET("text_editor/completion/put_callhint_tooltip_below_current_line"));
@@ -1862,28 +1867,33 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
int ot_mode = EditorSettings::get_singleton()->get("interface/editor/code_font_contextual_ligatures");
- switch (ot_mode) {
- case 1: { // Disable ligatures.
- text_editor->clear_opentype_features();
- text_editor->set_opentype_feature("calt", 0);
- } break;
- case 2: { // Custom.
- text_editor->clear_opentype_features();
- Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
- Dictionary ftrs;
- for (int i = 0; i < subtag.size(); i++) {
- Vector<String> subtag_a = subtag[i].split("=");
- if (subtag_a.size() == 2) {
- text_editor->set_opentype_feature(subtag_a[0], subtag_a[1].to_int());
- } else if (subtag_a.size() == 1) {
- text_editor->set_opentype_feature(subtag_a[0], 1);
+ Ref<FontVariation> fc = text_editor->get_theme_font(SNAME("font"));
+ if (fc.is_valid()) {
+ switch (ot_mode) {
+ case 1: { // Disable ligatures.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 0;
+ fc->set_opentype_features(ftrs);
+ } break;
+ case 2: { // Custom.
+ Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
+ Dictionary ftrs;
+ for (int i = 0; i < subtag.size(); i++) {
+ Vector<String> subtag_a = subtag[i].split("=");
+ if (subtag_a.size() == 2) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
+ } else if (subtag_a.size() == 1) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = 1;
+ }
}
- }
- } break;
- default: { // Default.
- text_editor->clear_opentype_features();
- text_editor->set_opentype_feature("calt", 1);
- } break;
+ fc->set_opentype_features(ftrs);
+ } break;
+ default: { // Default.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 1;
+ fc->set_opentype_features(ftrs);
+ } break;
+ }
}
text_editor->set_draw_line_numbers(true);
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index 764e842539..50eef7b8b8 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -136,7 +136,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent(font_size)), current.item->get_text(0), HORIZONTAL_ALIGNMENT_LEFT, rect.size.x, font_size, draw_color);
draw_color.a = 0.9f;
- float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1), font_size).width;
+ float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
if (value_position < 0) {
value_position = 0;
}
@@ -184,7 +184,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE));
String label = _create_label(e->get(), current.type);
- Size2 size = graph_font->get_string_size(label, font_size);
+ Size2 size = graph_font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN));
if (text_top_left_position.x < 0) {
text_top_left_position.x = from + MARKER_MARGIN;
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 1b1cdbd9ef..28b5d4be15 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -312,7 +312,7 @@ void EditorProfiler::_update_plot() {
if (graph_texture.is_null()) {
graph_texture.instantiate();
}
- graph_texture->create_from_image(img);
+ graph_texture->set_image(img);
}
graph_texture->update(img);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 9def646f3f..ee67cbdaea 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -306,7 +306,7 @@ void EditorVisualProfiler::_update_plot() {
if (graph_texture.is_null()) {
graph_texture.instantiate();
}
- graph_texture->create_from_image(img);
+ graph_texture->set_image(img);
}
graph_texture->update(img);
@@ -469,7 +469,7 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), color * Color(1, 1, 1, 0.5));
const String limit_str = String::num(graph_limit, 2) + " ms";
- graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
+ graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
if (graph_height_gpu > 0) {
@@ -480,11 +480,11 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), color * Color(1, 1, 1, 0.5));
const String limit_str = String::num(graph_limit, 2) + " ms";
- graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
+ graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
- graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
- graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
+ graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
+ graph->draw_string(font, Vector2(font->get_string_size("X", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
}
void EditorVisualProfiler::_graph_tex_mouse_exit() {
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 408d6af022..f8b82ecc51 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1422,6 +1422,10 @@ bool ScriptEditorDebugger::is_skip_breakpoints() {
void ScriptEditorDebugger::_error_activated() {
TreeItem *selected = error_tree->get_selected();
+ if (!selected) {
+ return;
+ }
+
TreeItem *ci = selected->get_first_child();
if (ci) {
selected->set_collapsed(!selected->is_collapsed());
@@ -1430,6 +1434,11 @@ void ScriptEditorDebugger::_error_activated() {
void ScriptEditorDebugger::_error_selected() {
TreeItem *selected = error_tree->get_selected();
+
+ if (!selected) {
+ return;
+ }
+
Array meta = selected->get_metadata(0);
if (meta.size() == 0) {
return;
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index e6cd1e0b48..a6c7970264 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -178,6 +178,20 @@ void DocTools::merge_from(const DocTools &p_data) {
}
}
+ for (int i = 0; i < c.annotations.size(); i++) {
+ DocData::MethodDoc &m = c.annotations.write[i];
+
+ for (int j = 0; j < cf.annotations.size(); j++) {
+ if (cf.annotations[j].name != m.name) {
+ continue;
+ }
+ const DocData::MethodDoc &mf = cf.annotations[j];
+
+ m.description = mf.description;
+ break;
+ }
+ }
+
for (int i = 0; i < c.properties.size(); i++) {
DocData::PropertyDoc &p = c.properties.write[i];
@@ -429,7 +443,7 @@ void DocTools::generate(bool p_basic_types) {
PropertyInfo retinfo = mb->get_return_info();
found_type = true;
- if (retinfo.type == Variant::INT && retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (retinfo.type == Variant::INT && retinfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
prop.enumeration = retinfo.class_name;
prop.type = "int";
} else if (retinfo.class_name != StringName()) {
@@ -575,6 +589,7 @@ void DocTools::generate(bool p_basic_types) {
constant.value = itos(ClassDB::get_integer_constant(name, E));
constant.is_value_valid = true;
constant.enumeration = ClassDB::get_integer_constant_enum(name, E);
+ constant.is_bitfield = ClassDB::is_enum_bitfield(name, constant.enumeration);
c.constants.push_back(constant);
}
@@ -959,8 +974,41 @@ void DocTools::generate(bool p_basic_types) {
c.constants.push_back(cd);
}
+ // Get annotations.
+ List<MethodInfo> ainfo;
+ lang->get_public_annotations(&ainfo);
+
+ for (const MethodInfo &ai : ainfo) {
+ DocData::MethodDoc atd;
+ atd.name = ai.name;
+
+ if (ai.flags & METHOD_FLAG_VARARG) {
+ if (!atd.qualifiers.is_empty()) {
+ atd.qualifiers += " ";
+ }
+ atd.qualifiers += "vararg";
+ }
+
+ DocData::return_doc_from_retinfo(atd, ai.return_val);
+
+ for (int j = 0; j < ai.arguments.size(); j++) {
+ DocData::ArgumentDoc ad;
+ DocData::argument_doc_from_arginfo(ad, ai.arguments[j]);
+
+ int darg_idx = j - (ai.arguments.size() - ai.default_arguments.size());
+ if (darg_idx >= 0) {
+ Variant default_arg = ai.default_arguments[darg_idx];
+ ad.default_value = default_arg.get_construct_string().replace("\n", " ");
+ }
+
+ atd.arguments.push_back(ad);
+ }
+
+ c.annotations.push_back(atd);
+ }
+
// Skip adding the lang if it doesn't expose anything (e.g. C#).
- if (c.methods.is_empty() && c.constants.is_empty()) {
+ if (c.methods.is_empty() && c.constants.is_empty() && c.annotations.is_empty()) {
continue;
}
@@ -1162,6 +1210,9 @@ Error DocTools::_load(Ref<XMLParser> parser) {
} else if (name2 == "signals") {
Error err2 = _parse_methods(parser, c.signals);
ERR_FAIL_COND_V(err2, err2);
+ } else if (name2 == "annotations") {
+ Error err2 = _parse_methods(parser, c.annotations);
+ ERR_FAIL_COND_V(err2, err2);
} else if (name2 == "members") {
while (parser->read() == OK) {
if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
@@ -1244,6 +1295,9 @@ Error DocTools::_load(Ref<XMLParser> parser) {
if (parser->has_attribute("enum")) {
constant2.enumeration = parser->get_attribute_value("enum");
}
+ if (parser->has_attribute("is_bitfield")) {
+ constant2.is_bitfield = parser->get_attribute_value("is_bitfield").to_lower() == "true";
+ }
if (!parser->is_empty()) {
parser->read();
if (parser->get_node_type() == XMLParser::NODE_TEXT) {
@@ -1424,7 +1478,11 @@ Error DocTools::save_classes(const String &p_default_path, const HashMap<String,
const DocData::ConstantDoc &k = c.constants[i];
if (k.is_value_valid) {
if (!k.enumeration.is_empty()) {
- _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">");
+ if (k.is_bitfield) {
+ _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\" is_bitfield=\"true\">");
+ } else {
+ _write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\" enum=\"" + k.enumeration + "\">");
+ }
} else {
_write_string(f, 2, "<constant name=\"" + k.name + "\" value=\"" + k.value + "\">");
}
@@ -1442,6 +1500,8 @@ Error DocTools::save_classes(const String &p_default_path, const HashMap<String,
_write_string(f, 1, "</constants>");
}
+ _write_method_doc(f, "annotation", c.annotations);
+
if (!c.theme_properties.is_empty()) {
c.theme_properties.sort();
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 89dc106717..fd121e73ab 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -1394,7 +1394,7 @@ Size2 EditorAudioMeterNotches::get_minimum_size() const {
for (int i = 0; i < notches.size(); i++) {
if (notches[i].render_db_value) {
- width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB", font_size).x);
+ width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x);
height += font_height;
}
}
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 64c234a07c..e9e3320a3d 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -534,6 +534,7 @@ void EditorData::remove_scene(int p_idx) {
}
memdelete(edited_scene[p_idx].root);
+ edited_scene.write[p_idx].root = nullptr;
}
if (current_edited_scene > p_idx) {
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 95f72476aa..af1345b205 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -731,9 +731,9 @@ void EditorFileDialog::update_file_name() {
String base_name = file_str.get_basename();
Vector<String> filter_substr = filter_str.split(";");
if (filter_substr.size() >= 2) {
- file_str = base_name + "." + filter_substr[0].strip_edges().lstrip("*.").to_lower();
+ file_str = base_name + "." + filter_substr[0].strip_edges().get_extension().to_lower();
} else {
- file_str = base_name + "." + filter_str.get_extension().strip_edges().to_lower();
+ file_str = base_name + "." + filter_str.strip_edges().get_extension().to_lower();
}
file->set_text(file_str);
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 51d4d474c5..d58dc98f07 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -37,212 +37,8 @@
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/font.h"
-#define MAKE_FALLBACKS(m_name) \
- m_name->add_data(FontArabic); \
- m_name->add_data(FontBengali); \
- m_name->add_data(FontDevanagari); \
- m_name->add_data(FontGeorgian); \
- m_name->add_data(FontHebrew); \
- m_name->add_data(FontMalayalam); \
- m_name->add_data(FontOriya); \
- m_name->add_data(FontSinhala); \
- m_name->add_data(FontTamil); \
- m_name->add_data(FontTelugu); \
- m_name->add_data(FontThai); \
- m_name->add_data(FontJapanese); \
- m_name->add_data(FontFallback);
-
-// Note: In some languages, the use of italic/slanted fonts is controversial. Therefore, we are limiting simulated slant to the main font (Latin, Cyrillic, and Greek) and using bold fonts for the rest.
-
-#define MAKE_FALLBACKS_SLANTED(m_name) \
- m_name->add_data(FontArabicBold); \
- m_name->add_data(FontBengaliBold); \
- m_name->add_data(FontDevanagariBold); \
- m_name->add_data(FontGeorgianBold); \
- m_name->add_data(FontHebrewBold); \
- m_name->add_data(FontMalayalamBold); \
- m_name->add_data(FontOriyaBold); \
- m_name->add_data(FontSinhalaBold); \
- m_name->add_data(FontTamilBold); \
- m_name->add_data(FontTeluguBold); \
- m_name->add_data(FontThaiBold); \
- m_name->add_data(FontJapaneseBold); \
- m_name->add_data(FontFallbackBold);
-
-#define MAKE_FALLBACKS_BOLD(m_name) \
- m_name->add_data(FontArabicBold); \
- m_name->add_data(FontBengaliBold); \
- m_name->add_data(FontDevanagariBold); \
- m_name->add_data(FontGeorgianBold); \
- m_name->add_data(FontHebrewBold); \
- m_name->add_data(FontMalayalamBold); \
- m_name->add_data(FontOriyaBold); \
- m_name->add_data(FontSinhalaBold); \
- m_name->add_data(FontTamilBold); \
- m_name->add_data(FontTeluguBold); \
- m_name->add_data(FontThaiBold); \
- m_name->add_data(FontJapaneseBold); \
- m_name->add_data(FontFallbackBold);
-
-#define MAKE_DEFAULT_FONT(m_name, m_variations) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- if (CustomFont.is_valid()) { \
- m_name->add_data(CustomFont); \
- m_name->add_data(DefaultFont); \
- } else { \
- m_name->add_data(DefaultFont); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
- m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS(m_name);
-
-#define MAKE_DEFAULT_FONT_MSDF(m_name, m_variations) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- if (CustomFont.is_valid()) { \
- m_name->add_data(CustomFontMSDF); \
- m_name->add_data(DefaultFontMSDF); \
- } else { \
- m_name->add_data(DefaultFontMSDF); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
- m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS(m_name);
-
-#define MAKE_SLANTED_FONT(m_name, m_variations) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- m_name.instantiate(); \
- if (CustomFontSlanted.is_valid()) { \
- m_name->add_data(CustomFontSlanted); \
- m_name->add_data(DefaultFontSlanted); \
- } else { \
- m_name->add_data(DefaultFontSlanted); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
- m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS_SLANTED(m_name);
-
-#define MAKE_BOLD_FONT(m_name, m_variations) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- if (CustomFontBold.is_valid()) { \
- m_name->add_data(CustomFontBold); \
- m_name->add_data(DefaultFontBold); \
- } else { \
- m_name->add_data(DefaultFontBold); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
- m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS_BOLD(m_name);
-
-#define MAKE_BOLD_FONT_MSDF(m_name, m_variations) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- if (CustomFontBold.is_valid()) { \
- m_name->add_data(CustomFontBoldMSDF); \
- m_name->add_data(DefaultFontBoldMSDF); \
- } else { \
- m_name->add_data(DefaultFontBoldMSDF); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- 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) \
- Ref<Font> m_name; \
- m_name.instantiate(); \
- if (CustomFontSource.is_valid()) { \
- m_name->add_data(CustomFontSource); \
- m_name->add_data(dfmono); \
- } else { \
- m_name->add_data(dfmono); \
- } \
- { \
- Dictionary variations; \
- if (!m_variations.is_empty()) { \
- Vector<String> variation_tags = m_variations.split(","); \
- for (int i = 0; i < variation_tags.size(); i++) { \
- Vector<String> tokens = variation_tags[i].split("="); \
- if (tokens.size() == 2) { \
- variations[tokens[0]] = tokens[1].to_float(); \
- } \
- } \
- } \
- m_name->set_variation_coordinates(variations); \
- } \
- m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
- m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
- MAKE_FALLBACKS(m_name);
-
-Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) {
- Ref<FontData> font;
+Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
+ Ref<FontFile> font;
font.instantiate();
Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
@@ -254,11 +50,15 @@ Ref<FontData> load_cached_external_font(const String &p_path, TextServer::Hintin
font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning);
+ if (r_fallbacks != nullptr) {
+ r_fallbacks->push_back(font);
+ }
+
return font;
}
-Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false) {
- Ref<FontData> font;
+Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
+ Ref<FontFile> font;
font.instantiate();
font->set_data_ptr(p_data, p_size);
@@ -268,14 +68,29 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
font->set_force_autohinter(p_autohint);
font->set_subpixel_positioning(p_font_subpixel_positioning);
+ if (r_fallbacks != nullptr) {
+ r_fallbacks->push_back(font);
+ }
+
return font;
}
+Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, TypedArray<Font> *r_fallbacks = nullptr) {
+ Ref<FontVariation> font_var;
+ font_var.instantiate();
+ font_var->set_base_font(p_font);
+ font_var->set_variation_embolden(p_embolden);
+
+ if (r_fallbacks != nullptr) {
+ r_fallbacks->push_back(font_var);
+ }
+
+ return font_var;
+}
+
void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- /* Custom font */
-
bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased");
int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting");
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning");
@@ -304,184 +119,268 @@ void editor_register_fonts(Ref<Theme> p_theme) {
break;
}
+ // Load built-in fonts.
const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
const float embolden_strength = 0.6;
+ Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false);
+ Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
+
+ TypedArray<Font> fallbacks;
+ Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks);
+ default_font->set_fallbacks(fallbacks);
+ default_font_msdf->set_fallbacks(fallbacks);
+
+ Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false);
+ Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
+
+ TypedArray<Font> fallbacks_bold;
+ Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold);
+ Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold);
+ Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold);
+ default_font_bold->set_fallbacks(fallbacks_bold);
+ default_font_bold_msdf->set_fallbacks(fallbacks_bold);
+
+ Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ default_font_mono->set_fallbacks(fallbacks);
+
+ // Init base font configs and load custom fonts.
String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font");
- Ref<FontData> CustomFont;
+ String custom_font_path_bold = EditorSettings::get_singleton()->get("interface/editor/main_font_bold");
+ String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
+
+ Ref<FontVariation> default_fc;
+ default_fc.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
- CustomFont = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ default_fc->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
+ default_fc->set_base_font(default_font);
}
+ default_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
+ default_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
- Ref<FontData> CustomFontMSDF;
+ Ref<FontVariation> default_fc_msdf;
+ default_fc_msdf.instantiate();
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
- CustomFontMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
+ Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_msdf);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ default_fc_msdf->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
+ default_fc_msdf->set_base_font(default_font_msdf);
}
+ default_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
+ default_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
- Ref<FontData> CustomFontSlanted;
- if (CustomFont.is_valid()) {
- CustomFontSlanted = CustomFont->duplicate();
- CustomFontSlanted->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
- }
-
- /* Custom Bold font */
-
- String custom_font_path_bold = EditorSettings::get_singleton()->get("interface/editor/main_font_bold");
- Ref<FontData> CustomFontBold;
+ Ref<FontVariation> bold_fc;
+ bold_fc.instantiate();
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
- CustomFontBold = load_cached_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_bold);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ bold_fc->set_base_font(custom_font);
+ } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
+ Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_bold);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ bold_fc->set_base_font(custom_font);
+ bold_fc->set_variation_embolden(embolden_strength);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
+ bold_fc->set_base_font(default_font_bold);
}
+ bold_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
+ bold_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
- if (CustomFont.is_valid() && !CustomFontBold.is_valid()) {
- CustomFontBold = CustomFont->duplicate();
- CustomFontBold->set_embolden(embolden_strength);
- }
-
- Ref<FontData> CustomFontBoldMSDF;
- if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
- CustomFontBoldMSDF = load_cached_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
+ Ref<FontVariation> bold_fc_msdf;
+ bold_fc_msdf.instantiate();
+ if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
+ Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_bold_msdf);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ bold_fc_msdf->set_base_font(custom_font);
+ } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
+ Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_bold_msdf);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ bold_fc_msdf->set_base_font(custom_font);
+ bold_fc_msdf->set_variation_embolden(embolden_strength);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
+ bold_fc_msdf->set_base_font(default_font_bold_msdf);
}
+ bold_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
+ bold_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
- /* Custom source code font */
-
- String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
- Ref<FontData> CustomFontSource;
+ Ref<FontVariation> mono_fc;
+ mono_fc.instantiate();
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
- CustomFontSource = load_cached_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning);
+ {
+ TypedArray<Font> fallback_custom;
+ fallback_custom.push_back(default_font_mono);
+ custom_font->set_fallbacks(fallback_custom);
+ }
+ mono_fc->set_base_font(custom_font);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
+ mono_fc->set_base_font(default_font_mono);
}
+ mono_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
+ mono_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
+
+ Ref<FontVariation> mono_other_fc = mono_fc->duplicate();
+
+ // Enable contextual alternates (coding ligatures) and custom features for the source editor font.
+ int ot_mode = EditorSettings::get_singleton()->get("interface/editor/code_font_contextual_ligatures");
+ switch (ot_mode) {
+ case 1: { // Disable ligatures.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 0;
+ mono_fc->set_opentype_features(ftrs);
+ } break;
+ case 2: { // Custom.
+ Vector<String> subtag = String(EditorSettings::get_singleton()->get("interface/editor/code_font_custom_opentype_features")).split(",");
+ Dictionary ftrs;
+ for (int i = 0; i < subtag.size(); i++) {
+ Vector<String> subtag_a = subtag[i].split("=");
+ if (subtag_a.size() == 2) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
+ } else if (subtag_a.size() == 1) {
+ ftrs[TS->name_to_tag(subtag_a[0])] = 1;
+ }
+ }
+ mono_fc->set_opentype_features(ftrs);
+ } break;
+ default: { // Default.
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 1;
+ mono_fc->set_opentype_features(ftrs);
+ } break;
+ }
+
+ {
+ // Disable contextual alternates (coding ligatures).
+ Dictionary ftrs;
+ ftrs[TS->name_to_tag("calt")] = 0;
+ mono_other_fc->set_opentype_features(ftrs);
+ }
+
+ Ref<FontVariation> italic_fc = default_fc->duplicate();
+ italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
- /* Noto Sans */
-
- Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> DefaultFontMSDF = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
- Ref<FontData> DefaultFontBold = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> DefaultFontBoldMSDF = load_cached_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true);
- Ref<FontData> FontArabic = load_cached_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontArabicBold = load_cached_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontBengali = load_cached_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontBengaliBold = load_cached_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontDevanagari = load_cached_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontDevanagariBold = load_cached_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontGeorgian = load_cached_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontGeorgianBold = load_cached_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontHebrew = load_cached_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontHebrewBold = load_cached_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontMalayalam = load_cached_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontMalayalamBold = load_cached_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontOriya = load_cached_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontOriyaBold = load_cached_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontSinhala = load_cached_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontSinhalaBold = load_cached_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontTamil = load_cached_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontTamilBold = load_cached_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontTelugu = load_cached_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontTeluguBold = load_cached_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontThai = load_cached_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontThaiBold = load_cached_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
-
- Ref<FontData> DefaultFontSlanted = DefaultFont->duplicate();
- DefaultFontSlanted->set_transform(Transform2D(1.0, 0.3, 0.0, 1.0, 0.0, 0.0));
-
- /* Droid Sans */
-
- Ref<FontData> FontFallback = load_cached_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Ref<FontData> FontJapanese = load_cached_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
-
- Ref<FontData> FontFallbackBold = FontFallback->duplicate();
- FontFallbackBold->set_embolden(embolden_strength);
- Ref<FontData> FontJapaneseBold = FontJapanese->duplicate();
- FontJapaneseBold->set_embolden(embolden_strength);
-
- /* Hack */
-
- Ref<FontData> dfmono = load_cached_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
- Dictionary opentype_features;
- opentype_features["calt"] = 0;
- dfmono->set_opentype_feature_overrides(opentype_features); // Disable contextual alternates (coding ligatures).
-
- // Default font
- MAKE_DEFAULT_FONT(df, String());
- p_theme->set_default_font(df); // Default theme font
+ // Setup theme.
+
+ p_theme->set_default_font(default_fc); // Default theme font config.
p_theme->set_default_font_size(default_font_size);
- p_theme->set_font_size("main_size", "EditorFonts", default_font_size);
- p_theme->set_font("main", "EditorFonts", df);
+ // Main font.
- MAKE_DEFAULT_FONT_MSDF(df_msdf, String());
- p_theme->set_font("main_msdf", "EditorFonts", df_msdf);
+ p_theme->set_font("main", "EditorFonts", default_fc);
+ p_theme->set_font("main_msdf", "EditorFonts", default_fc_msdf);
+ p_theme->set_font_size("main_size", "EditorFonts", default_font_size);
- // Bold font
- MAKE_BOLD_FONT(df_bold, String());
- MAKE_SLANTED_FONT(df_italic, String());
+ p_theme->set_font("bold", "EditorFonts", bold_fc);
+ p_theme->set_font("main_bold_msdf", "EditorFonts", bold_fc_msdf);
p_theme->set_font_size("bold_size", "EditorFonts", default_font_size);
- p_theme->set_font("bold", "EditorFonts", df_bold);
- MAKE_BOLD_FONT_MSDF(df_bold_msdf, String());
- p_theme->set_font("main_bold_msdf", "EditorFonts", df_bold_msdf);
+ // Title font.
- // Title font
+ p_theme->set_font("title", "EditorFonts", bold_fc);
p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 1 * EDSCALE);
- p_theme->set_font("title", "EditorFonts", df_bold);
+ p_theme->set_font("main_button_font", "EditorFonts", bold_fc);
p_theme->set_font_size("main_button_font_size", "EditorFonts", default_font_size + 1 * EDSCALE);
- p_theme->set_font("main_button_font", "EditorFonts", df_bold);
- p_theme->set_font("font", "Label", df);
+ p_theme->set_font("font", "Label", default_fc);
p_theme->set_type_variation("HeaderSmall", "Label");
- p_theme->set_font("font", "HeaderSmall", df_bold);
+ p_theme->set_font("font", "HeaderSmall", bold_fc);
p_theme->set_font_size("font_size", "HeaderSmall", default_font_size);
p_theme->set_type_variation("HeaderMedium", "Label");
- p_theme->set_font("font", "HeaderMedium", df_bold);
+ p_theme->set_font("font", "HeaderMedium", bold_fc);
p_theme->set_font_size("font_size", "HeaderMedium", default_font_size + 1 * EDSCALE);
p_theme->set_type_variation("HeaderLarge", "Label");
- p_theme->set_font("font", "HeaderLarge", df_bold);
+ p_theme->set_font("font", "HeaderLarge", bold_fc);
p_theme->set_font_size("font_size", "HeaderLarge", default_font_size + 3 * EDSCALE);
// 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);
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("doc_bold", "EditorFonts", df_bold);
- p_theme->set_font("doc_italic", "EditorFonts", df_italic);
+ p_theme->set_font("doc", "EditorFonts", default_fc);
+ p_theme->set_font("doc_bold", "EditorFonts", bold_fc);
+ p_theme->set_font("doc_italic", "EditorFonts", italic_fc);
p_theme->set_font_size("doc_title_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE);
- p_theme->set_font("doc_title", "EditorFonts", df_bold);
+ p_theme->set_font("doc_title", "EditorFonts", bold_fc);
p_theme->set_font_size("doc_source_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE);
- p_theme->set_font("doc_source", "EditorFonts", df_code);
+ p_theme->set_font("doc_source", "EditorFonts", mono_fc);
p_theme->set_font_size("doc_keyboard_size", "EditorFonts", (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE);
- p_theme->set_font("doc_keyboard", "EditorFonts", df_code);
+ p_theme->set_font("doc_keyboard", "EditorFonts", mono_fc);
// Ruler font
p_theme->set_font_size("rulers_size", "EditorFonts", 8 * EDSCALE);
- p_theme->set_font("rulers", "EditorFonts", df);
+ p_theme->set_font("rulers", "EditorFonts", default_fc);
// Rotation widget font
p_theme->set_font_size("rotation_control_size", "EditorFonts", 14 * EDSCALE);
- p_theme->set_font("rotation_control", "EditorFonts", df);
+ p_theme->set_font("rotation_control", "EditorFonts", default_fc);
// Code font
p_theme->set_font_size("source_size", "EditorFonts", int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE);
- p_theme->set_font("source", "EditorFonts", df_code);
+ p_theme->set_font("source", "EditorFonts", mono_fc);
p_theme->set_font_size("expression_size", "EditorFonts", (int(EDITOR_GET("interface/editor/code_font_size")) - 1) * EDSCALE);
- p_theme->set_font("expression", "EditorFonts", df_code);
+ p_theme->set_font("expression", "EditorFonts", mono_other_fc);
p_theme->set_font_size("output_source_size", "EditorFonts", int(EDITOR_GET("run/output/font_size")) * EDSCALE);
- p_theme->set_font("output_source", "EditorFonts", df_code);
+ p_theme->set_font("output_source", "EditorFonts", mono_other_fc);
p_theme->set_font_size("status_source_size", "EditorFonts", default_font_size);
- p_theme->set_font("status_source", "EditorFonts", df_code);
+ p_theme->set_font("status_source", "EditorFonts", mono_other_fc);
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 36360954d9..a674451d1e 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -125,6 +125,9 @@ void EditorHelp::_class_desc_select(const String &p_select) {
} else if (tag == "constant") {
topic = "class_constant";
table = &this->constant_line;
+ } else if (tag == "annotation") {
+ topic = "class_annotation";
+ table = &this->annotation_line;
} else if (tag == "theme_item") {
topic = "theme_item";
table = &this->theme_property_line;
@@ -183,7 +186,7 @@ void EditorHelp::_class_desc_resized(bool p_force_update_theme) {
// The margins increase as the width of the editor help container increases.
Ref<Font> doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("doc_source_size"), SNAME("EditorFonts"));
- real_t char_width = doc_code_font->get_char_size('x', 0, font_size).width;
+ real_t char_width = doc_code_font->get_char_size('x', font_size).width;
const int new_display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5;
if (display_margin != new_display_margin || p_force_update_theme) {
display_margin = new_display_margin;
@@ -274,7 +277,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
class_desc->add_text(" ");
}
- if (p_overview && !p_method.description.is_empty()) {
+ if (p_overview && !p_method.description.strip_edges().is_empty()) {
class_desc->push_meta("@method " + p_method.name);
}
@@ -282,7 +285,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
_add_text(p_method.name);
class_desc->pop();
- if (p_overview && !p_method.description.is_empty()) {
+ if (p_overview && !p_method.description.strip_edges().is_empty()) {
class_desc->pop(); //meta
}
@@ -412,7 +415,7 @@ void EditorHelp::_update_method_list(const Vector<DocData::MethodDoc> p_methods,
class_desc->pop(); //cell
}
- if (!m[i].description.is_empty() || m[i].errors_returned.size() > 0) {
+ if (!m[i].description.strip_edges().is_empty() || m[i].errors_returned.size() > 0) {
r_method_descrpitons = true;
}
@@ -611,7 +614,7 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
// Brief description
- if (!cd.brief_description.is_empty()) {
+ if (!cd.brief_description.strip_edges().is_empty()) {
class_desc->push_color(text_color);
class_desc->push_font(doc_bold_font);
class_desc->push_indent(1);
@@ -625,7 +628,7 @@ void EditorHelp::_update_doc() {
}
// Class description
- if (!cd.description.is_empty()) {
+ if (!cd.description.strip_edges().is_empty()) {
section_line.push_back(Pair<String, int>(TTR("Description"), class_desc->get_paragraph_count() - 2));
description_line = class_desc->get_paragraph_count() - 2;
class_desc->push_color(title_color);
@@ -692,7 +695,7 @@ void EditorHelp::_update_doc() {
if (cd.is_script_doc) {
has_properties = false;
for (int i = 0; i < cd.properties.size(); i++) {
- if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.is_empty()) {
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.strip_edges().is_empty()) {
continue;
}
has_properties = true;
@@ -718,7 +721,7 @@ void EditorHelp::_update_doc() {
for (int i = 0; i < cd.properties.size(); i++) {
// Ignore undocumented private.
- if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.is_empty()) {
+ if (cd.properties[i].name.begins_with("_") && cd.properties[i].description.strip_edges().is_empty()) {
continue;
}
property_line[cd.properties[i].name] = class_desc->get_paragraph_count() - 2; //gets overridden if description
@@ -743,7 +746,7 @@ void EditorHelp::_update_doc() {
describe = true;
}
- if (!cd.properties[i].description.is_empty()) {
+ if (!cd.properties[i].description.strip_edges().is_empty()) {
describe = true;
}
@@ -856,7 +859,7 @@ void EditorHelp::_update_doc() {
}
}
// Ignore undocumented non virtual private.
- if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty() && !cd.methods[i].qualifiers.contains("virtual")) {
+ if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.strip_edges().is_empty() && !cd.methods[i].qualifiers.contains("virtual")) {
continue;
}
methods.push_back(cd.methods[i]);
@@ -976,7 +979,7 @@ void EditorHelp::_update_doc() {
class_desc->pop(); // monofont
// Theme item description.
- if (!cd.theme_properties[i].description.is_empty()) {
+ if (!cd.theme_properties[i].description.strip_edges().is_empty()) {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
class_desc->push_indent(1);
@@ -1018,8 +1021,8 @@ void EditorHelp::_update_doc() {
signal_line[cd.signals[i].name] = class_desc->get_paragraph_count() - 2; // Gets overridden if description.
class_desc->push_font(doc_code_font); // monofont
- class_desc->push_color(headline_color);
_add_bulletpoint();
+ class_desc->push_color(headline_color);
_add_text(cd.signals[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1048,7 +1051,7 @@ void EditorHelp::_update_doc() {
class_desc->add_text(")");
class_desc->pop();
class_desc->pop(); // end monofont
- if (!cd.signals[i].description.is_empty()) {
+ if (!cd.signals[i].description.strip_edges().is_empty()) {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
class_desc->push_indent(1);
@@ -1079,7 +1082,7 @@ void EditorHelp::_update_doc() {
enums[cd.constants[i].enumeration].push_back(cd.constants[i]);
} else {
// Ignore undocumented private.
- if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.is_empty()) {
+ if (cd.constants[i].name.begins_with("_") && cd.constants[i].description.strip_edges().is_empty()) {
continue;
}
constants.push_back(cd.constants[i]);
@@ -1105,7 +1108,11 @@ void EditorHelp::_update_doc() {
class_desc->push_font(doc_code_font);
class_desc->push_color(title_color);
- class_desc->add_text("enum ");
+ if (E.value.size() && E.value[0].is_bitfield) {
+ class_desc->add_text("flags ");
+ } else {
+ class_desc->add_text("enum ");
+ }
class_desc->pop();
String e = E.key;
if ((e.get_slice_count(".") > 1) && (e.get_slice(".", 0) == edited_class)) {
@@ -1151,8 +1158,8 @@ void EditorHelp::_update_doc() {
constant_line[enum_list[i].name] = class_desc->get_paragraph_count() - 2;
class_desc->push_font(doc_code_font);
- class_desc->push_color(headline_color);
_add_bulletpoint();
+ class_desc->push_color(headline_color);
_add_text(enum_list[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1236,7 +1243,7 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
- if (!constants[i].description.is_empty()) {
+ if (!constants[i].description.strip_edges().is_empty()) {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
_add_text(DTR(constants[i].description));
@@ -1255,6 +1262,112 @@ void EditorHelp::_update_doc() {
}
}
+ // Annotations
+ if (!cd.annotations.is_empty()) {
+ if (sort_methods) {
+ cd.annotations.sort();
+ }
+
+ section_line.push_back(Pair<String, int>(TTR("Annotations"), class_desc->get_paragraph_count() - 2));
+ class_desc->push_color(title_color);
+ class_desc->push_font(doc_title_font);
+ class_desc->push_font_size(doc_title_font_size);
+ class_desc->add_text(TTR("Annotations"));
+ class_desc->pop(); // font size
+ class_desc->pop(); // font
+ class_desc->pop(); // color
+
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+ class_desc->push_indent(1);
+
+ for (int i = 0; i < cd.annotations.size(); i++) {
+ annotation_line[cd.annotations[i].name] = class_desc->get_paragraph_count() - 2; // Gets overridden if description.
+
+ class_desc->push_font(doc_code_font); // monofont
+ _add_bulletpoint();
+ class_desc->push_color(headline_color);
+ _add_text(cd.annotations[i].name);
+ class_desc->pop();
+
+ if (cd.annotations[i].arguments.size() > 0) {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text("(");
+ class_desc->pop();
+ for (int j = 0; j < cd.annotations[i].arguments.size(); j++) {
+ class_desc->push_color(text_color);
+ if (j > 0) {
+ class_desc->add_text(", ");
+ }
+
+ _add_text(cd.annotations[i].arguments[j].name);
+ class_desc->add_text(": ");
+ _add_type(cd.annotations[i].arguments[j].type);
+ if (!cd.annotations[i].arguments[j].default_value.is_empty()) {
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(" = ");
+ class_desc->pop();
+ _add_text(cd.annotations[i].arguments[j].default_value);
+ }
+
+ class_desc->pop();
+ }
+
+ if (cd.annotations[i].qualifiers.contains("vararg")) {
+ class_desc->push_color(text_color);
+ if (cd.annotations[i].arguments.size()) {
+ class_desc->add_text(", ");
+ }
+ class_desc->push_color(symbol_color);
+ class_desc->add_text("...");
+ class_desc->pop();
+ class_desc->pop();
+ }
+
+ class_desc->push_color(symbol_color);
+ class_desc->add_text(")");
+ class_desc->pop();
+ }
+
+ if (!cd.annotations[i].qualifiers.is_empty()) {
+ class_desc->push_color(qualifier_color);
+ class_desc->add_text(" ");
+ _add_text(cd.annotations[i].qualifiers);
+ class_desc->pop();
+ }
+
+ class_desc->pop(); // end monofont
+
+ if (!cd.annotations[i].description.strip_edges().is_empty()) {
+ class_desc->push_font(doc_font);
+ class_desc->push_color(comment_color);
+ class_desc->push_indent(1);
+ _add_text(DTR(cd.annotations[i].description));
+ class_desc->pop(); // indent
+ class_desc->pop();
+ class_desc->pop(); // font
+ } else {
+ class_desc->push_indent(1);
+ class_desc->add_image(get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
+ class_desc->add_text(" ");
+ class_desc->push_color(comment_color);
+ if (cd.is_script_doc) {
+ class_desc->append_text(TTR("There is currently no description for this annotation."));
+ } else {
+ class_desc->append_text(TTR("There is currently no description for this annotation. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ }
+ class_desc->pop();
+ class_desc->pop(); // indent
+ }
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+ }
+
// Property descriptions
if (property_descr) {
section_line.push_back(Pair<String, int>(TTR("Property Descriptions"), class_desc->get_paragraph_count() - 2));
@@ -1501,6 +1614,10 @@ void EditorHelp::_help_callback(const String &p_topic) {
if (constant_line.has(name)) {
line = constant_line[name];
}
+ } else if (what == "class_annotation") {
+ if (annotation_line.has(name)) {
+ line = annotation_line[name];
+ }
} else if (what == "class_global") {
if (constant_line.has(name)) {
line = constant_line[name];
diff --git a/editor/editor_help.h b/editor/editor_help.h
index 7f91a8102d..9f8da938f1 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -110,6 +110,7 @@ class EditorHelp : public VBoxContainer {
HashMap<String, int> property_line;
HashMap<String, int> theme_property_line;
HashMap<String, int> constant_line;
+ HashMap<String, int> annotation_line;
HashMap<String, int> enum_line;
HashMap<String, HashMap<String, int>> enum_values_line;
int description_line = 0;
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 2bf0cd2f20..dc47719f0a 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -322,7 +322,7 @@ void EditorProperty::_notification(int p_what) {
Ref<Texture2D> pinned_icon = get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"));
int margin_w = get_theme_constant(SNAME("hseparator"), SNAME("Tree")) * 2;
int total_icon_w = margin_w + pinned_icon->get_width();
- int text_w = font->get_string_size(label, font_size, rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT, text_limit - total_icon_w).x;
+ int text_w = font->get_string_size(label, rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT, text_limit - total_icon_w, font_size).x;
int y = (size.height - pinned_icon->get_height()) / 2;
if (rtl) {
draw_texture(pinned_icon, Vector2(size.width - ofs - text_w - total_icon_w, y), color);
@@ -1087,7 +1087,7 @@ void EditorInspectorCategory::_notification(int p_what) {
int hs = get_theme_constant(SNAME("h_separation"), SNAME("Tree"));
- int w = font->get_string_size(label, font_size).width;
+ int w = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
if (icon.is_valid()) {
w += hs + icon->get_width();
}
@@ -3429,6 +3429,7 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
if (editor_property_map.has(p_path)) {
for (EditorProperty *E : editor_property_map[p_path]) {
+ E->set_checked(p_checked);
E->update_property();
E->update_revert_and_pin_status();
E->update_cache();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index e3caaf93c6..64665833df 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -134,6 +134,7 @@
#include "editor/plugins/audio_stream_editor_plugin.h"
#include "editor/plugins/audio_stream_randomizer_editor_plugin.h"
#include "editor/plugins/bit_map_editor_plugin.h"
+#include "editor/plugins/bone_map_editor_plugin.h"
#include "editor/plugins/camera_3d_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
@@ -145,7 +146,7 @@
#include "editor/plugins/debugger_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
-#include "editor/plugins/font_editor_plugin.h"
+#include "editor/plugins/font_config_plugin.h"
#include "editor/plugins/gdextension_export_plugin.h"
#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
@@ -164,7 +165,6 @@
#include "editor/plugins/navigation_polygon_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/occluder_instance_3d_editor_plugin.h"
-#include "editor/plugins/ot_features_plugin.h"
#include "editor/plugins/packed_scene_translation_parser_plugin.h"
#include "editor/plugins/path_2d_editor_plugin.h"
#include "editor/plugins/path_3d_editor_plugin.h"
@@ -186,7 +186,6 @@
#include "editor/plugins/sprite_frames_editor_plugin.h"
#include "editor/plugins/style_box_editor_plugin.h"
#include "editor/plugins/sub_viewport_preview_editor_plugin.h"
-#include "editor/plugins/text_control_editor_plugin.h"
#include "editor/plugins/text_editor.h"
#include "editor/plugins/texture_3d_editor_plugin.h"
#include "editor/plugins/texture_editor_plugin.h"
@@ -2333,6 +2332,13 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
return;
}
+ play_button->set_pressed(false);
+ play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
+ play_scene_button->set_pressed(false);
+ play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
+ play_custom_scene_button->set_pressed(false);
+ play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
+
String write_movie_file;
if (write_movie_button->is_pressed()) {
if (p_current && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->has_meta("movie_file")) {
@@ -2347,13 +2353,6 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
}
- play_button->set_pressed(false);
- play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
- play_scene_button->set_pressed(false);
- play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons")));
- play_custom_scene_button->set_pressed(false);
- play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons")));
-
String run_filename;
if (p_current || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) {
@@ -2793,9 +2792,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RUN_SETTINGS: {
project_settings_editor->popup_project_settings();
} break;
- case RUN_WRITE_MOVIE: {
- _update_write_movie_icon();
- } break;
case FILE_INSTALL_ANDROID_SOURCE: {
if (p_confirmed) {
export_template_manager->install_android_template();
@@ -4047,10 +4043,8 @@ Ref<ImageTexture> EditorNode::_load_custom_class_icon(const String &p_path) cons
Ref<Image> img = memnew(Image);
Error err = ImageLoader::load_image(p_path, img);
if (err == OK) {
- Ref<ImageTexture> icon = memnew(ImageTexture);
img->resize(16 * EDSCALE, 16 * EDSCALE, Image::INTERPOLATE_LANCZOS);
- icon->create_from_image(img);
- return icon;
+ return ImageTexture::create_from_image(img);
}
}
return nullptr;
@@ -4957,14 +4951,6 @@ String EditorNode::get_run_playing_scene() const {
return run_filename;
}
-void EditorNode::_update_write_movie_icon() {
- if (write_movie_button->is_pressed()) {
- write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWriteEnabled"), SNAME("EditorIcons")));
- } else {
- write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
- }
-}
-
void EditorNode::_immediate_dialog_confirmed() {
immediate_dialog_confirmed = true;
}
@@ -5405,9 +5391,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
Ref<Image> img = texture->get_image();
img = img->duplicate();
img->resize(48, 48); // meh
- Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture));
- resized_pic->create_from_image(img);
- preview = resized_pic;
+ preview = ImageTexture::create_from_image(img);
}
drag_preview->set_texture(preview);
@@ -6137,7 +6121,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary");
EDITOR_DEF("interface/inspector/default_color_picker_mode", 0);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL", PROPERTY_USAGE_DEFAULT));
EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_OKHSL_CIRCLE);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle", PROPERTY_USAGE_DEFAULT));
@@ -6733,15 +6717,12 @@ EditorNode::EditorNode() {
write_movie_button->set_pressed(false);
write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
write_movie_button->set_focus_mode(Control::FOCUS_NONE);
- write_movie_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_WRITE_MOVIE));
write_movie_button->set_tooltip(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file."));
- // Restore these values to something more useful so it ignores the theme
- write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.4));
- write_movie_button->add_theme_color_override("icon_pressed_color", Color(1, 1, 1, 1));
- write_movie_button->add_theme_color_override("icon_hover_color", Color(1.2, 1.2, 1.2, 0.4));
- write_movie_button->add_theme_color_override("icon_hover_pressed_color", Color(1.2, 1.2, 1.2, 1));
- write_movie_button->add_theme_color_override("icon_focus_color", Color(1, 1, 1, 1));
- write_movie_button->add_theme_color_override("icon_disabled_color", Color(1, 1, 1, 0.4));
+
+ // This button behaves differently, so color it as such.
+ write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.7));
+ write_movie_button->add_theme_color_override("icon_pressed_color", gui_base->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ write_movie_button->add_theme_color_override("icon_hover_color", Color(1, 1, 1, 0.9));
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
menu_hb->add_child(right_menu_hb);
@@ -7071,12 +7052,10 @@ EditorNode::EditorNode() {
ScriptTextEditor::register_editor(); // Register one for text scripts.
TextEditor::register_editor();
- // Asset Library can't work on Web editor for now as most assets are sourced
- // directly from GitHub which does not set CORS.
if (AssetLibraryEditorPlugin::is_available()) {
add_editor_plugin(memnew(AssetLibraryEditorPlugin));
} else {
- WARN_PRINT("Asset Library not available, as it requires SSL to work.");
+ print_verbose("Asset Library not available (due to using Web editor, or SSL support disabled).");
}
// Add interface before adding plugins.
@@ -7124,7 +7103,6 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(CollisionShape2DEditorPlugin));
add_editor_plugin(memnew(CurveEditorPlugin));
add_editor_plugin(memnew(FontEditorPlugin));
- add_editor_plugin(memnew(OpenTypeFeaturesEditorPlugin));
add_editor_plugin(memnew(TextureEditorPlugin));
add_editor_plugin(memnew(TextureLayeredEditorPlugin));
add_editor_plugin(memnew(Texture3DEditorPlugin));
@@ -7139,11 +7117,11 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(GPUParticlesCollisionSDF3DEditorPlugin));
add_editor_plugin(memnew(InputEventEditorPlugin));
add_editor_plugin(memnew(SubViewportPreviewEditorPlugin));
- add_editor_plugin(memnew(TextControlEditorPlugin));
add_editor_plugin(memnew(ControlEditorPlugin));
add_editor_plugin(memnew(GradientTexture2DEditorPlugin));
add_editor_plugin(memnew(BitMapEditorPlugin));
add_editor_plugin(memnew(RayCast2DEditorPlugin));
+ add_editor_plugin(memnew(BoneMapEditorPlugin));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
add_editor_plugin(EditorPlugins::create(i));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c327a73ce9..07d565314d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -173,7 +173,6 @@ private:
RUN_PLAY_CUSTOM_SCENE,
RUN_SETTINGS,
RUN_USER_DATA_FOLDER,
- RUN_WRITE_MOVIE,
RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_VCS_METADATA,
@@ -669,7 +668,6 @@ private:
void _pick_main_scene_custom_action(const String &p_custom_action_name);
void _immediate_dialog_confirmed();
- void _update_write_movie_icon();
void _select_default_main_screen_plugin();
void _bottom_panel_switch(bool p_enable, int p_idx);
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 639846861b..d9c2a42114 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -133,8 +133,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
Main::iteration();
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
ERR_CONTINUE(!img.is_valid() || img->is_empty());
- Ref<ImageTexture> it(memnew(ImageTexture));
- it->create_from_image(img);
+ Ref<ImageTexture> it = ImageTexture::create_from_image(img);
RS::get_singleton()->free(inst);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 70622e85ff..d06d22ae5b 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3010,12 +3010,7 @@ void EditorPropertyColor::_popup_closed() {
void EditorPropertyColor::_picker_created() {
// get default color picker mode from editor settings
int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
- if (default_color_mode == 1) {
- picker->get_picker()->set_hsv_mode(true);
- } else if (default_color_mode == 2) {
- picker->get_picker()->set_raw_mode(true);
- }
-
+ picker->get_picker()->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
picker->get_picker()->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
}
@@ -3175,7 +3170,20 @@ bool EditorPropertyNodePath::is_drop_valid(const Dictionary &p_drag_data) const
return false;
}
Array nodes = p_drag_data["nodes"];
- return nodes.size() == 1;
+ if (nodes.size() != 1) {
+ return false;
+ }
+
+ Node *dropped_node = get_tree()->get_edited_scene_root()->get_node(nodes[0]);
+ ERR_FAIL_NULL_V(dropped_node, false);
+
+ for (const StringName &E : valid_types) {
+ if (dropped_node->is_class(E)) {
+ return true;
+ }
+ }
+
+ return false;
}
void EditorPropertyNodePath::update_property() {
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 4d53ddb344..16ebecb8be 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -534,8 +534,6 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, HashSet<Strin
p_vector->insert("Texture2D");
} else if (base == "ShaderMaterial") {
p_vector->insert("Shader");
- } else if (base == "Font") {
- p_vector->insert("FontData");
} else if (base == "Texture2D") {
p_vector->insert("Image");
}
@@ -675,22 +673,12 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_
break;
}
- if (at == "Font" && Ref<FontData>(dropped_resource).is_valid()) {
- Ref<Font> font = edited_resource;
- if (!font.is_valid()) {
- font.instantiate();
- }
- font->add_data(dropped_resource);
- dropped_resource = font;
- break;
- }
-
if (at == "Texture2D" && Ref<Image>(dropped_resource).is_valid()) {
Ref<ImageTexture> texture = edited_resource;
if (!texture.is_valid()) {
texture.instantiate();
}
- texture->create_from_image(dropped_resource);
+ texture->set_image(dropped_resource);
dropped_resource = texture;
break;
}
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index dffb378408..b84e654d42 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -184,7 +184,7 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
small_image = small_image->duplicate();
small_image->resize(small_thumbnail_size, small_thumbnail_size, Image::INTERPOLATE_CUBIC);
r_small_texture.instantiate();
- r_small_texture->create_from_image(small_image);
+ r_small_texture->set_image(small_image);
}
break;
@@ -300,14 +300,14 @@ void EditorResourcePreview::_iterate() {
cache_valid = false;
} else {
texture.instantiate();
- texture->create_from_image(img);
+ texture->set_image(img);
if (has_small_texture) {
if (small_img->load(cache_base + "_small.png") != OK) {
cache_valid = false;
} else {
small_texture.instantiate();
- small_texture->create_from_image(small_img);
+ small_texture->set_image(small_img);
}
}
}
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 6ce9e5fa6f..854885c707 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -49,9 +49,7 @@ void EditorRunNative::_notification(int p_what) {
im->clear_mipmaps();
if (!im->is_empty()) {
im->resize(16 * EDSCALE, 16 * EDSCALE);
- Ref<ImageTexture> small_icon;
- small_icon.instantiate();
- small_icon->create_from_image(im);
+ Ref<ImageTexture> small_icon = ImageTexture::create_from_image(im);
MenuButton *mb = memnew(MenuButton);
mb->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native), varray(i));
mb->connect("pressed", callable_mp(this, &EditorRunNative::run_native), varray(-1, i));
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index ad9c547693..fa8643af86 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -444,6 +444,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Inspector
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/inspector/max_array_dictionary_items_per_page", 20, "10,100,1")
+ EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/inspector/show_low_level_opentype_features", false, "")
// Theme
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Custom")
@@ -763,6 +764,7 @@ void EditorSettings::_load_godot2_text_editor_theme() {
_initial_set("text_editor/theme/highlighting/completion_selected_color", Color(0.26, 0.26, 0.27));
_initial_set("text_editor/theme/highlighting/completion_existing_color", Color(0.87, 0.87, 0.87, 0.13));
_initial_set("text_editor/theme/highlighting/completion_scroll_color", Color(1, 1, 1, 0.29));
+ _initial_set("text_editor/theme/highlighting/completion_scroll_hovered_color", Color(1, 1, 1, 0.4));
_initial_set("text_editor/theme/highlighting/completion_font_color", Color(0.67, 0.67, 0.67));
_initial_set("text_editor/theme/highlighting/text_color", Color(0.67, 0.67, 0.67));
_initial_set("text_editor/theme/highlighting/line_number_color", Color(0.67, 0.67, 0.67, 0.4));
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index f23f0cf758..c651d6bf6e 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -286,7 +286,7 @@ void EditorSpinSlider::_draw_spin_slider() {
int sep_base = 4 * EDSCALE;
int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
- int label_width = font->get_string_size(label, font_size).width;
+ int label_width = font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
int number_width = size.width - sb->get_minimum_size().width - label_width - sep;
Ref<Texture2D> updown = get_theme_icon(is_read_only() ? SNAME("updown_disabled") : SNAME("updown"), SNAME("SpinBox"));
@@ -324,7 +324,10 @@ void EditorSpinSlider::_draw_spin_slider() {
int suffix_start = numstr.length();
RID num_rid = TS->create_shaped_text();
- TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size);
+ TS->shaped_text_add_string(num_rid, numstr + U"\u2009" + suffix, font->get_rids(), font_size, font->get_opentype_features());
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(num_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
float text_start = rtl ? Math::round(sb->get_offset().x) : Math::round(sb->get_offset().x + label_width + sep);
Vector2 text_ofs = rtl ? Vector2(text_start + (number_width - TS->shaped_text_get_width(num_rid)), vofs) : Vector2(text_start, vofs);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 10412eac41..13109478e4 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -97,7 +97,6 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
return p_texture;
}
- Ref<ImageTexture> texture(memnew(ImageTexture));
Ref<Image> img = p_texture->get_image();
ERR_FAIL_NULL_V(img, Ref<Texture2D>());
img = img->duplicate();
@@ -109,14 +108,12 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
img->flip_x();
}
- texture->create_from_image(img);
- return texture;
+ return ImageTexture::create_from_image(img);
}
#ifdef MODULE_SVG_ENABLED
// See also `generate_icon()` in `scene/resources/default_theme.cpp`.
static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, float p_saturation = 1.0, Dictionary p_convert_colors = Dictionary()) {
- Ref<ImageTexture> icon = memnew(ImageTexture);
Ref<Image> img = memnew(Image);
// Upsample icon generation only if the editor scale isn't an integer multiplier.
@@ -129,9 +126,9 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color,
if (p_saturation != 1.0) {
img->adjust_bcs(1.0, 1.0, p_saturation);
}
- icon->create_from_image(img); // in this case filter really helps
- return icon;
+ // In this case filter really helps.
+ return ImageTexture::create_from_image(img);
}
#endif
@@ -1683,6 +1680,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color completion_existing_color = alpha2;
// Same opacity as the scroll grabber editor icon.
const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29);
+ const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4);
const Color completion_font_color = font_color;
const Color text_color = font_color;
const Color line_number_color = dim_color;
@@ -1721,6 +1719,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true);
setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true);
setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true);
setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true);
setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true);
setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true);
@@ -1766,6 +1765,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color"));
theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color"));
theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color"));
+ theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color"));
theme->set_color("completion_font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_font_color"));
theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color"));
theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color"));
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index e1c9689f73..81b71b5609 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -764,8 +764,8 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
int font_size = _results_display->get_theme_font_size(SNAME("font_size"));
Rect2 match_rect = rect;
- match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), font_size).x;
- match_rect.size.x = font->get_string_size(_search_text_label->get_text(), font_size).x;
+ match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
+ match_rect.size.x = font->get_string_size(_search_text_label->get_text(), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
match_rect.position.y += 1 * EDSCALE;
match_rect.size.y -= 2 * EDSCALE;
diff --git a/editor/icons/BoneMapHumanBody.svg b/editor/icons/BoneMapHumanBody.svg
new file mode 100644
index 0000000000..2c2c5db1f6
--- /dev/null
+++ b/editor/icons/BoneMapHumanBody.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m926.5 217.162c-11.5-2-26.03 4.547-37.5 6.5-15.723 2.678-25.238 3.24-33.333 5.167-1.227.292-3.103.763-5.792.958 0 0-.019.16-.052.437-36.819.994-106.823-6.062-138.156-2.062-23.816 3.041-86.334-5.667-105.667-6-13.911-.239-59.292-4.583-71.75-2.5-.667-4.083-1.5-10.75.95-17.468 14.881-7.246 27.229-21.569 35.341-38.467.922 4.424 6.252 4.929 12.459-14.231 5.662-17.478 2.324-22.254-2.313-22.525.172-2.056.279-4.105.313-6.142.788-48.041-15-78.667-69-78.667s-69.787 30.626-69 78.667c.033 2.036.141 4.086.313 6.142-4.637.271-7.975 5.048-2.313 22.525 6.207 19.16 11.537 18.655 12.459 14.231 8.113 16.897 20.461 31.221 35.342 38.467 2.449 6.718 1.617 13.385.949 17.468-12.457-2.083-57.838 2.261-71.75 2.5-19.332.333-81.85 9.041-105.666 6-31.333-4-101.337 3.056-138.156 2.062-.033-.276-.053-.437-.053-.437-2.689-.195-4.564-.666-5.791-.958-8.096-1.927-17.611-2.489-33.334-5.167-11.469-1.953-26-8.5-37.5-6.5-3.367.586 6 9.834 15.5 12.334 13.635 3.588 25.25 10.666 36 13.166-2.25 3.75-15.59 7.063-23 12-5.336 3.557 6.5 6.5 12 5 20.842-5.684 22.973.389 37.514-9.019 30.078 4.078 102.537 20.514 122.154 14.186 12.457-4.018 100.332 7.083 142.332 5.833 6.039-.18 1.656 65.563 2 73.5 3 69-16.842 133.135-18.666 169.667-1.92 38.42-3.42 57.919 7.666 131.333 6.967 46.126-2.521 82.079-2 94 6 137 29 172 4 221-14 27.44 67.449 26.958 65 9-3.012-22.092-12.666-22.333-10.666-46.333 1.896-22.768 16.049-151.298 8.666-206.667-2-15 0-26 2-66 2.355-47.101 7-88 14-123 7 35 11.645 75.899 14 123 2 40 4 51 2 66-7.383 55.369 6.77 183.899 8.667 206.667 2 24-7.654 24.241-10.667 46.333-2.449 17.958 79 18.44 65-9-25-49-2-84 4-221 .522-11.921-8.966-47.874-2-94 11.086-73.414 9.586-92.913 7.667-131.333-1.824-36.532-21.667-100.667-18.667-169.667.345-7.938-4.039-73.68 2-73.5 42 1.25 129.876-9.852 142.333-5.833 19.616 6.328 92.076-10.107 122.153-14.186 14.541 9.407 16.673 3.335 37.514 9.019 5.5 1.5 17.336-1.443 12-5-7.409-4.937-20.75-8.25-23-12 10.75-2.5 22.366-9.578 36.001-13.166 9.5-2.5 18.866-11.748 15.499-12.334z" fill="#b2b2b2"/></svg>
diff --git a/editor/icons/BoneMapHumanFace.svg b/editor/icons/BoneMapHumanFace.svg
new file mode 100644
index 0000000000..6cb21140bc
--- /dev/null
+++ b/editor/icons/BoneMapHumanFace.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m788.105 552.967c17.995-57.892 31.896-124.566 30.875-198.071-3.758-270.403-249.846-251.479-295.568-244.947-359.868 51.409-219.047 452.358-220.453 496.426-4.899 153.499 83.686 170.991 161.665 215.554 2.646 1.512 7.259 1.786 13.313 1.111 7.223 25.179 11.762 59.035 9.548 75.638-3.266 24.495 209.021 24.495 209.021 0 0-62.883 12.233-124.363 33.827-188.89 7.143-2.284 16.054-7.601 25.963-16.95 13.681-12.908 34.839-21.774 45.726-63.145 15.615-59.338 3.869-76.074-13.917-76.726z" fill="#b2b2b2"/></svg>
diff --git a/editor/icons/BoneMapHumanLeftHand.svg b/editor/icons/BoneMapHumanLeftHand.svg
new file mode 100644
index 0000000000..08c68bb4be
--- /dev/null
+++ b/editor/icons/BoneMapHumanLeftHand.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m703.906 786.098c7.046-66.929 28.135-153.363 18.529-260.192-1.143-12.71-4.5-48.282-4.46-82.732.025-21.174-2.111-48.505-1.975-64.174.167-19.333-.428-41.584-.625-55.755-1.052-75.44-13.225-85.827-30.813-85.827-17.246 0-26.77 14.266-27.062 84.582-.061 14.42.5 51 .5 58.5 0 17.508-.333 34.167 0 53.5.447 25.955-4.279 68-9 68-3.902 0-8.099-39.299-9.575-76.999-.756-19.326-3.219-58.336-2.6-70.102 1.759-33.413.474-58.914 1.537-90.165 3.183-93.607-13.016-111.729-34.695-111.729-21.973 0-35.979 57.688-34.849 114.224.128 6.394-1.165 50.739.188 89.859.754 21.811-1.07 49.627-1.683 69.67-1.095 35.768-5.755 63.896-8.869 63.896-2.641 0-4.135-32.584-5.456-65.706-.859-21.557-4.468-58.477-3.664-83.616 1.886-59.012-1.139-110.226-1.063-121.501.635-94.955-14.66-123.101-36.052-123.101-21.476 0-37.188 30.192-36.6 123.343.067 10.53-2.62 99.926-1.759 121.816.865 21.992-2.773 65.062-3.517 84.818-1.299 34.521-6.49 63.947-9.124 63.947-3.281 0-10.794-25.638-11.724-60.965-.587-22.275 1.231-50.99.624-70.688-1.257-40.707-3.175-64.631-3.877-99.708-1.945-97.182-16.352-106.289-38.142-106.289-17.957 0-32.453 28.673-32.657 115.03-.065 27.702-2.429 62.626-.315 94.329.805 12.081-.622 42.512-1.875 73.894-.799 20.007-1.102 47.501-1.137 63.775-.17 78.595-26.712 133.424-36.555 131.308-30.333-6.521-51.648-43.918-71.219-117.307-10.551-39.566-36.667-71.149-69.9-77.813-25.9-5.193-19.783 46.161-1.319 125.293 8.65 37.068 27.909 86.227 39.566 122.655 31.653 98.917 125.574 188.563 160.903 228.546 17.146 19.403 236.894 19.403 264.59 0 11.525-8.07 43.087-101.557 45.724-126.616z" fill="#b2b2b2"/></svg>
diff --git a/editor/icons/BoneMapHumanRightHand.svg b/editor/icons/BoneMapHumanRightHand.svg
new file mode 100644
index 0000000000..4e40af35d8
--- /dev/null
+++ b/editor/icons/BoneMapHumanRightHand.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 1024 1024" height="1024" viewBox="0 0 1024 1024" width="1024" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h1024v1024h-1024z" fill="#3f3f3f"/><path d="m320.094 786.098c-7.046-66.929-28.135-153.363-18.529-260.192 1.143-12.71 4.5-48.282 4.46-82.732-.025-21.174 2.111-48.505 1.975-64.174-.167-19.333.428-41.584.625-55.755 1.052-75.44 13.225-85.827 30.813-85.827 17.246 0 26.77 14.266 27.062 84.582.061 14.42-.5 51-.5 58.5 0 17.508.333 34.167 0 53.5-.447 25.955 4.279 68 9 68 3.902 0 8.099-39.299 9.575-76.999.756-19.326 3.219-58.336 2.6-70.102-1.759-33.413-.474-58.914-1.537-90.165-3.183-93.607 13.016-111.729 34.695-111.729 21.973 0 35.979 57.688 34.849 114.224-.128 6.394 1.165 50.739-.188 89.859-.754 21.811 1.07 49.627 1.683 69.67 1.095 35.768 5.755 63.896 8.869 63.896 2.641 0 4.135-32.584 5.456-65.706.859-21.557 4.468-58.477 3.664-83.616-1.886-59.012 1.139-110.226 1.063-121.501-.635-94.955 14.66-123.101 36.052-123.101 21.476 0 37.188 30.192 36.6 123.343-.067 10.53 2.62 99.926 1.759 121.816-.865 21.992 2.773 65.062 3.517 84.818 1.299 34.521 6.49 63.947 9.124 63.947 3.281 0 10.794-25.638 11.724-60.965.587-22.275-1.231-50.99-.624-70.688 1.257-40.707 3.176-64.631 3.877-99.708 1.945-97.182 16.352-106.289 38.142-106.289 17.957 0 32.453 28.673 32.657 115.03.065 27.702 2.429 62.626.314 94.329-.805 12.081.622 42.512 1.875 73.894.799 20.007 1.102 47.501 1.137 63.775.171 78.595 26.713 133.424 36.556 131.308 30.333-6.521 51.648-43.918 71.219-117.307 10.551-39.566 36.667-71.149 69.9-77.813 25.9-5.193 19.783 46.161 1.318 125.293-8.649 37.068-27.909 86.227-39.566 122.655-31.652 98.917-125.573 188.563-160.902 228.546-17.146 19.403-236.894 19.403-264.59 0-11.525-8.07-43.087-101.557-45.724-126.616z" fill="#b2b2b2"/></svg>
diff --git a/editor/icons/BoneMapperHandle.svg b/editor/icons/BoneMapperHandle.svg
new file mode 100644
index 0000000000..8c7d7e1d70
--- /dev/null
+++ b/editor/icons/BoneMapperHandle.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 12 12" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill-opacity=".2941" r="5"/><circle cx="6" cy="6" fill="#fff" r="4"/></svg>
diff --git a/editor/icons/BoneMapperHandleCircle.svg b/editor/icons/BoneMapperHandleCircle.svg
new file mode 100644
index 0000000000..ecf97669b8
--- /dev/null
+++ b/editor/icons/BoneMapperHandleCircle.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 12 12" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" fill="#fff" r="3"/></svg>
diff --git a/editor/icons/BoneMapperHandleSelected.svg b/editor/icons/BoneMapperHandleSelected.svg
new file mode 100644
index 0000000000..729a443f6e
--- /dev/null
+++ b/editor/icons/BoneMapperHandleSelected.svg
@@ -0,0 +1 @@
+<svg enable-background="new -506.5 517.5 12 12" height="12" viewBox="-506.5 517.5 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><circle cx="-500.5" cy="523.5" fill-opacity=".2941" r="5"/><g fill="#fff"><circle cx="-500.5" cy="523.5" r="4"/><path d="m-499.5 517.5h5v5h-1v-4h-4z"/><path d="m-494.5 524.5v5h-5v-1h4v-4z"/><path d="m-501.5 529.5h-5v-5h1v4h4z"/><path d="m-506.5 522.5v-5h5v1h-4v4z"/></g></svg>
diff --git a/editor/icons/Font.svg b/editor/icons/Font.svg
index 2c8d7cb43e..dda1aa577e 100644
--- a/editor/icons/Font.svg
+++ b/editor/icons/Font.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(0 -1036.4)"><path d="m1 1037.4h14v2h-14z"/><path d="m7 1037.4h2v14h-2z"/><path d="m5 1050.4h6v1h-6z"/><path d="m1037.4-2h4v1h-4z" transform="rotate(90)"/><path d="m1037.4-15h4v1h-4z" transform="rotate(90)"/><path d="m2 3v2a2 2 0 0 1 2-2z" transform="translate(0 1036.4)"/><path d="m12 3a2 2 0 0 1 2 2v-2z" transform="translate(0 1036.4)"/><path d="m5 1050.4a2 2 0 0 0 2-2v2z"/><path d="m11 1050.4a2 2 0 0 1 -2-2v2z"/></g></svg>
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="M1 1h14v2H1z"/><path d="M7 1h2v14H7z"/><path d="M5 14h6v1H5zM2 1v4H1V1zm13 0v4h-1V1zM2 3v2a2 2 0 0 1 2-2zm10 0a2 2 0 0 1 2 2V3zM5 14a2 2 0 0 0 2-2v2zm6 0a2 2 0 0 1-2-2v2z"/></g></svg>
diff --git a/editor/icons/FontData.svg b/editor/icons/FontData.svg
deleted file mode 100644
index 4cb6412081..0000000000
--- a/editor/icons/FontData.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2zm0 5v2h2v-2zm0 3v2h2v-2zm0 3v2h2v-2zm3 0v2h2v-2z" fill="#e0e0e0"/><path d="m4 5v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/FontFile.svg b/editor/icons/FontFile.svg
new file mode 100644
index 0000000000..4b94fd0d74
--- /dev/null
+++ b/editor/icons/FontFile.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V3h2a1 1 0 0 1 1 1h1V1h-6Z" fill="#e0e0e0"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6Z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/FontVariation.svg b/editor/icons/FontVariation.svg
new file mode 100644
index 0000000000..eaad049fce
--- /dev/null
+++ b/editor/icons/FontVariation.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M2.437 1 1.379 4h1A.84 1.192 50 0 1 3.73 3h2L3.615 9a.84 1.192 50 0 1-1.352 1l-.353 1h4l.353-1a.84 1.192 50 0 1-.648-1l2.116-6h2a.84 1.192 50 0 1 .648 1h1l1.058-3h-6Z" fill="#e0e0e0"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6Z" fill="#ff5f5f"/></svg>
diff --git a/editor/icons/MainMovieWriteEnabled.svg b/editor/icons/MainMovieWriteEnabled.svg
deleted file mode 100644
index b12ea38bed..0000000000
--- a/editor/icons/MainMovieWriteEnabled.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 4-1.535V14h.002a2 2 0 0 0 .266 1A2 2 0 0 0 14 16h1v-2h-.5a.5.5 0 0 1-.5-.5V8a6 6 0 0 0-6-6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm3.441 2a1 1 0 0 1 .89.5 1 1 0 0 1-.366 1.365 1 1 0 0 1-1.367-.365 1 1 0 0 1 .367-1.365A1 1 0 0 1 11.44 5zm-6.953.002a1 1 0 0 1 .547.133A1 1 0 0 1 5.402 6.5a1 1 0 0 1-1.367.365A1 1 0 0 1 3.67 5.5a1 1 0 0 1 .818-.498zM4.512 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365A1 1 0 0 1 3.67 10.5a1 1 0 0 1 .365-1.365A1 1 0 0 1 4.512 9zm6.904.002a1 1 0 0 1 .549.133 1 1 0 0 1 .365 1.365 1 1 0 0 1-1.365.365 1 1 0 0 1-.367-1.365 1 1 0 0 1 .818-.498zM8 11a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#e0e0e0" style="fill:#ee5353;fill-opacity:1"/></svg>
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f7fe334828..fa261496f0 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -41,50 +41,44 @@
/* Settings data */
/*************************************************************************/
-class DynamicFontImportSettingsData : public RefCounted {
- GDCLASS(DynamicFontImportSettingsData, RefCounted)
- friend class DynamicFontImportSettings;
-
- HashMap<StringName, Variant> settings;
- HashMap<StringName, Variant> defaults;
- List<ResourceImporter::ImportOption> options;
- DynamicFontImportSettings *owner = nullptr;
-
- bool _set(const StringName &p_name, const Variant &p_value) {
- if (defaults.has(p_name) && defaults[p_name] == p_value) {
- settings.erase(p_name);
- } else {
- settings[p_name] = p_value;
- }
- return true;
+bool DynamicFontImportSettingsData::_set(const StringName &p_name, const Variant &p_value) {
+ if (defaults.has(p_name) && defaults[p_name] == p_value) {
+ settings.erase(p_name);
+ } else {
+ settings[p_name] = p_value;
}
+ return true;
+}
- bool _get(const StringName &p_name, Variant &r_ret) const {
- if (settings.has(p_name)) {
- r_ret = settings[p_name];
- return true;
- }
- if (defaults.has(p_name)) {
- r_ret = defaults[p_name];
- return true;
- }
- return false;
+bool DynamicFontImportSettingsData::_get(const StringName &p_name, Variant &r_ret) const {
+ if (settings.has(p_name)) {
+ r_ret = settings[p_name];
+ return true;
+ }
+ if (defaults.has(p_name)) {
+ r_ret = defaults[p_name];
+ return true;
}
+ return false;
+}
- void _get_property_list(List<PropertyInfo> *p_list) const {
- for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- if (owner && owner->import_settings_data.is_valid()) {
- if (owner->import_settings_data->get("multichannel_signed_distance_field") && (E->get().option.name == "size" || E->get().option.name == "outline_size" || E->get().option.name == "oversampling")) {
- continue;
- }
- if (!owner->import_settings_data->get("multichannel_signed_distance_field") && (E->get().option.name == "msdf_pixel_range" || E->get().option.name == "msdf_size")) {
- continue;
- }
+void DynamicFontImportSettingsData::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
+ if (owner && owner->import_settings_data.is_valid()) {
+ if (owner->import_settings_data->get("multichannel_signed_distance_field") && (E->get().option.name == "size" || E->get().option.name == "outline_size" || E->get().option.name == "oversampling")) {
+ continue;
+ }
+ if (!owner->import_settings_data->get("multichannel_signed_distance_field") && (E->get().option.name == "msdf_pixel_range" || E->get().option.name == "msdf_size")) {
+ continue;
}
- p_list->push_back(E->get().option);
}
+ p_list->push_back(E->get().option);
}
-};
+}
+
+Ref<FontFile> DynamicFontImportSettingsData::get_font() const {
+ return fd;
+}
/*************************************************************************/
/* Glyph ranges */
@@ -454,58 +448,32 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p
void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_property) {
// Update font preview.
- if (p_edited_property == "face_index") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_face_index(import_settings_data->get("face_index"));
- }
- } else if (p_edited_property == "antialiased") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased"));
- }
- } else if (p_edited_property == "generate_mipmaps") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_generate_mipmaps(import_settings_data->get("generate_mipmaps"));
- }
- } else if (p_edited_property == "multichannel_signed_distance_field") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
- }
- _variation_selected();
- _variations_validate();
- } else if (p_edited_property == "msdf_pixel_range") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
- }
- } else if (p_edited_property == "msdf_size") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_msdf_size(import_settings_data->get("msdf_size"));
- }
- } else if (p_edited_property == "force_autohinter") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
- }
- } else if (p_edited_property == "hinting") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
- }
- } else if (p_edited_property == "subpixel_positioning") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
- }
- } else if (p_edited_property == "embolden") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
- }
- } else if (p_edited_property == "transform") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
- }
- } else if (p_edited_property == "oversampling") {
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
+ if (font_preview.is_valid()) {
+ if (p_edited_property == "antialiased") {
+ font_preview->set_antialiased(import_settings_data->get("antialiased"));
+ } else if (p_edited_property == "generate_mipmaps") {
+ font_preview->set_generate_mipmaps(import_settings_data->get("generate_mipmaps"));
+ } else if (p_edited_property == "multichannel_signed_distance_field") {
+ font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
+ _variation_selected();
+ _variations_validate();
+ } else if (p_edited_property == "msdf_pixel_range") {
+ font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
+ } else if (p_edited_property == "msdf_size") {
+ font_preview->set_msdf_size(import_settings_data->get("msdf_size"));
+ } else if (p_edited_property == "force_autohinter") {
+ font_preview->set_force_autohinter(import_settings_data->get("force_autohinter"));
+ } else if (p_edited_property == "hinting") {
+ font_preview->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
+ } else if (p_edited_property == "subpixel_positioning") {
+ font_preview->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
+ } else if (p_edited_property == "oversampling") {
+ font_preview->set_oversampling(import_settings_data->get("oversampling"));
}
}
+
font_preview_label->add_theme_font_override("font", font_preview);
+ font_preview_label->add_theme_font_size_override("font_size", 200 * EDSCALE);
font_preview_label->update();
}
@@ -534,6 +502,7 @@ void DynamicFontImportSettings::_variation_add() {
import_variation_data->options = options_variations;
inspector_vars->edit(import_variation_data.ptr());
import_variation_data->notify_property_list_changed();
+ import_variation_data->fd = font_main;
vars_item->set_metadata(0, import_variation_data);
@@ -548,6 +517,10 @@ void DynamicFontImportSettings::_variation_selected() {
inspector_vars->edit(import_variation_data.ptr());
import_variation_data->notify_property_list_changed();
+
+ label_glyphs->set_text(TTR("Preloaded glyphs: ") + itos(import_variation_data->selected_glyphs.size()));
+ _range_selected();
+ _change_text_opts();
}
}
@@ -611,63 +584,91 @@ void DynamicFontImportSettings::_variations_validate() {
}
/*************************************************************************/
-/* Page 3 callbacks: Text to select glyphs */
+/* Page 2.1 callbacks: Text to select glyphs */
/*************************************************************************/
void DynamicFontImportSettings::_change_text_opts() {
- Vector<String> ftr = ftr_edit->get_text().split(",");
- for (int i = 0; i < ftr.size(); i++) {
- Vector<String> tokens = ftr[i].split("=");
- if (tokens.size() == 2) {
- text_edit->set_opentype_feature(tokens[0], tokens[1].to_int());
- } else if (tokens.size() == 1) {
- text_edit->set_opentype_feature(tokens[0], 1);
- }
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
}
- text_edit->set_language(lang_edit->get_text());
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
+ Ref<FontVariation> font_main_text;
+ font_main_text.instantiate();
+ font_main_text->set_base_font(font_main);
+ font_main_text->set_opentype_features(text_settings_data->get("opentype_features"));
+ font_main_text->set_variation_opentype(import_variation_data->get("variation_opentype"));
+ font_main_text->set_variation_embolden(import_variation_data->get("variation_embolden"));
+ font_main_text->set_variation_face_index(import_variation_data->get("variation_face_index"));
+ font_main_text->set_variation_transform(import_variation_data->get("variation_transform"));
+
+ text_edit->add_theme_font_override("font", font_main_text);
}
void DynamicFontImportSettings::_glyph_clear() {
- selected_glyphs.clear();
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(selected_glyphs.size()));
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
+ import_variation_data->selected_glyphs.clear();
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
_range_selected();
}
void DynamicFontImportSettings::_glyph_text_selected() {
- Dictionary ftrs;
- Vector<String> ftr = ftr_edit->get_text().split(",");
- for (int i = 0; i < ftr.size(); i++) {
- Vector<String> tokens = ftr[i].split("=");
- if (tokens.size() == 2) {
- ftrs[tokens[0]] = tokens[1].to_int();
- } else if (tokens.size() == 1) {
- ftrs[tokens[0]] = 1;
- }
- }
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
RID text_rid = TS->create_shaped_text();
if (text_rid.is_valid()) {
- TS->shaped_text_add_string(text_rid, text_edit->get_text(), font_main->get_rids(), 16, ftrs, text_edit->get_language());
+ TS->shaped_text_add_string(text_rid, text_edit->get_text(), font_main->get_rids(), 16, text_settings_data->get("opentype_features"), text_settings_data->get("language"));
TS->shaped_text_shape(text_rid);
const Glyph *gl = TS->shaped_text_get_glyphs(text_rid);
const int gl_size = TS->shaped_text_get_glyph_count(text_rid);
for (int i = 0; i < gl_size; i++) {
if (gl[i].font_rid.is_valid() && gl[i].index != 0) {
- selected_glyphs.insert(gl[i].index);
+ import_variation_data->selected_glyphs.insert(gl[i].index);
}
}
TS->free_rid(text_rid);
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(selected_glyphs.size()));
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
}
_range_selected();
}
/*************************************************************************/
-/* Page 4 callbacks: Character map */
+/* Page 2.2 callbacks: Character map */
/*************************************************************************/
void DynamicFontImportSettings::_glyph_selected() {
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
TreeItem *item = glyph_table->get_selected();
ERR_FAIL_NULL(item);
@@ -685,7 +686,7 @@ void DynamicFontImportSettings::_glyph_selected() {
item->clear_custom_bg_color(glyph_table->get_selected_column());
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(selected_glyphs.size()));
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
item = glyph_tree->get_selected();
ERR_FAIL_NULL(item);
@@ -698,7 +699,7 @@ void DynamicFontImportSettings::_glyph_selected() {
total_chars--;
}
- if (selected_chars.has(i)) {
+ if (import_variation_data->selected_chars.has(i)) {
selected_count++;
}
}
@@ -728,6 +729,16 @@ void DynamicFontImportSettings::_range_selected() {
}
void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
glyph_table->clear();
TreeItem *root = glyph_table->create_item();
@@ -740,6 +751,8 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
TreeItem *item = nullptr;
int col = 0;
+ Ref<Font> font_main_big = font_main->duplicate();
+
for (int32_t c = p_start; c <= p_end; c++) {
if (col == 0) {
item = glyph_table->create_item(root);
@@ -752,7 +765,7 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
if (font_main->has_char(c)) {
item->set_text(col + 1, String::chr(c));
item->set_custom_color(col + 1, Color(1, 1, 1));
- if (selected_chars.has(c) || (font_main->get_data(0).is_valid() && selected_glyphs.has(font_main->get_data(0)->get_glyph_index(get_theme_font_size(SNAME("font_size")) * 2, c)))) {
+ if (import_variation_data->selected_chars.has(c) || import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, c))) {
item->set_custom_color(col + 1, fcol);
item->set_custom_bg_color(col + 1, scol);
} else {
@@ -765,7 +778,8 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
item->set_metadata(col + 1, c);
item->set_text_alignment(col + 1, HORIZONTAL_ALIGNMENT_CENTER);
item->set_selectable(col + 1, true);
- item->set_custom_font(col + 1, font_main);
+
+ item->set_custom_font(col + 1, font_main_big);
item->set_custom_font_size(col + 1, get_theme_font_size(SNAME("font_size")) * 2);
col++;
@@ -773,41 +787,61 @@ void DynamicFontImportSettings::_edit_range(int32_t p_start, int32_t p_end) {
col = 0;
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(selected_glyphs.size()));
+ label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(import_variation_data->selected_glyphs.size()));
}
bool DynamicFontImportSettings::_char_update(int32_t p_char) {
- if (selected_chars.has(p_char)) {
- selected_chars.erase(p_char);
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
return false;
- } else if (font_main->get_data(0).is_valid() && selected_glyphs.has(font_main->get_data(0)->get_glyph_index(get_theme_font_size(SNAME("font_size")) * 2, p_char))) {
- selected_glyphs.erase(font_main->get_data(0)->get_glyph_index(get_theme_font_size(SNAME("font_size")) * 2, p_char));
+ }
+
+ if (import_variation_data->selected_chars.has(p_char)) {
+ import_variation_data->selected_chars.erase(p_char);
+ return false;
+ } else if (font_main.is_valid() && font_main.is_valid() && import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, p_char))) {
+ import_variation_data->selected_glyphs.erase(font_main->get_glyph_index(16, p_char));
return false;
} else {
- selected_chars.insert(p_char);
+ import_variation_data->selected_chars.insert(p_char);
return true;
}
}
void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) {
+ Ref<DynamicFontImportSettingsData> import_variation_data;
+
+ TreeItem *vars_item = vars_list->get_selected();
+ if (vars_item) {
+ import_variation_data = vars_item->get_metadata(0);
+ }
+ if (import_variation_data.is_null()) {
+ return;
+ }
+
bool all_selected = true;
for (int32_t i = p_start; i <= p_end; i++) {
if (font_main->has_char(i)) {
- if (font_main->get_data(0).is_valid()) {
- all_selected = all_selected && (selected_chars.has(i) || (font_main->get_data(0).is_valid() && selected_glyphs.has(font_main->get_data(0)->get_glyph_index(get_theme_font_size(SNAME("font_size")) * 2, i))));
+ if (font_main.is_valid()) {
+ all_selected = all_selected && (import_variation_data->selected_chars.has(i) || import_variation_data->selected_glyphs.has(font_main->get_glyph_index(16, i)));
} else {
- all_selected = all_selected && selected_chars.has(i);
+ all_selected = all_selected && import_variation_data->selected_chars.has(i);
}
}
}
for (int32_t i = p_start; i <= p_end; i++) {
if (font_main->has_char(i)) {
if (!all_selected) {
- selected_chars.insert(i);
+ import_variation_data->selected_chars.insert(i);
} else {
- selected_chars.erase(i);
- if (font_main->get_data(0).is_valid()) {
- selected_glyphs.erase(font_main->get_data(0)->get_glyph_index(get_theme_font_size(SNAME("font_size")) * 2, i));
+ import_variation_data->selected_chars.erase(i);
+ if (font_main.is_valid()) {
+ import_variation_data->selected_glyphs.erase(font_main->get_glyph_index(16, i));
}
}
}
@@ -820,106 +854,6 @@ void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) {
}
/*************************************************************************/
-/* Page 5 callbacks: CMetadata override */
-/*************************************************************************/
-
-void DynamicFontImportSettings::_lang_add() {
- locale_select->popup_locale_dialog();
-}
-
-void DynamicFontImportSettings::_lang_add_item(const String &p_locale) {
- TreeItem *lang_item = lang_list->create_item(lang_list_root);
- ERR_FAIL_NULL(lang_item);
-
- lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- lang_item->set_editable(0, true);
- lang_item->set_checked(0, false);
- lang_item->set_text(1, p_locale);
- lang_item->set_editable(1, true);
- lang_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- lang_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
-}
-
-void DynamicFontImportSettings::_lang_remove(Object *p_item, int p_column, int p_id, MouseButton p_button) {
- if (p_button != MouseButton::LEFT) {
- return;
- }
-
- TreeItem *lang_item = (TreeItem *)p_item;
- ERR_FAIL_NULL(lang_item);
-
- lang_list_root->remove_child(lang_item);
- memdelete(lang_item);
-}
-
-void DynamicFontImportSettings::_ot_add() {
- menu_ot->set_position(ot_list->get_screen_transform().xform(ot_list->get_local_mouse_position()));
- menu_ot->set_size(Vector2(1, 1));
- menu_ot->popup();
-}
-
-void DynamicFontImportSettings::_ot_add_item(int p_option) {
- String name = TS->tag_to_name(p_option);
- for (TreeItem *ot_item = ot_list_root->get_first_child(); ot_item; ot_item = ot_item->get_next()) {
- if (ot_item->get_text(0) == name) {
- return;
- }
- }
- TreeItem *ot_item = ot_list->create_item(ot_list_root);
- ERR_FAIL_NULL(ot_item);
-
- ot_item->set_text(0, name);
- ot_item->set_editable(0, false);
- ot_item->set_text(1, "1");
- ot_item->set_editable(1, true);
- ot_item->add_button(2, ot_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- ot_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
-}
-
-void DynamicFontImportSettings::_ot_remove(Object *p_item, int p_column, int p_id, MouseButton p_button) {
- if (p_button != MouseButton::LEFT) {
- return;
- }
-
- TreeItem *ot_item = (TreeItem *)p_item;
- ERR_FAIL_NULL(ot_item);
-
- ot_list_root->remove_child(ot_item);
- memdelete(ot_item);
-}
-
-void DynamicFontImportSettings::_script_add() {
- menu_scripts->set_position(script_list->get_screen_position() + script_list->get_local_mouse_position());
- menu_scripts->reset_size();
- menu_scripts->popup();
-}
-
-void DynamicFontImportSettings::_script_add_item(int p_option) {
- TreeItem *script_item = script_list->create_item(script_list_root);
- ERR_FAIL_NULL(script_item);
-
- script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- script_item->set_editable(0, true);
- script_item->set_checked(0, false);
- script_item->set_text(1, script_codes[p_option]);
- script_item->set_editable(1, true);
- script_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- script_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
-}
-
-void DynamicFontImportSettings::_script_remove(Object *p_item, int p_column, int p_id, MouseButton p_button) {
- if (p_button != MouseButton::LEFT) {
- return;
- }
-
- TreeItem *script_item = (TreeItem *)p_item;
- ERR_FAIL_NULL(script_item);
-
- script_list_root->remove_child(script_item);
- memdelete(script_item);
-}
-
-/*************************************************************************/
/* Common */
/*************************************************************************/
@@ -938,10 +872,7 @@ void DynamicFontImportSettings::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
- add_lang->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- add_script->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
add_var->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- add_ot->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
}
@@ -958,90 +889,40 @@ void DynamicFontImportSettings::_re_import() {
main_settings["force_autohinter"] = import_settings_data->get("force_autohinter");
main_settings["hinting"] = import_settings_data->get("hinting");
main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning");
- main_settings["embolden"] = import_settings_data->get("embolden");
- main_settings["transform"] = import_settings_data->get("transform");
main_settings["oversampling"] = import_settings_data->get("oversampling");
+ main_settings["fallbacks"] = import_settings_data->get("fallbacks");
main_settings["compress"] = import_settings_data->get("compress");
- Vector<String> variations;
+ Array configurations;
for (TreeItem *vars_item = vars_list_root->get_first_child(); vars_item; vars_item = vars_item->get_next()) {
- String variation;
Ref<DynamicFontImportSettingsData> import_variation_data = vars_item->get_metadata(0);
ERR_FAIL_NULL(import_variation_data);
- String name = vars_item->get_text(0);
- variation += ("name=" + name);
+ Dictionary preload_config;
+ preload_config["name"] = vars_item->get_text(0);
+
for (const KeyValue<StringName, Variant> &E : import_variation_data->settings) {
- if (!variation.is_empty()) {
- variation += ",";
- }
- variation += (String(E.key) + "=" + String(E.value));
- }
- variations.push_back(variation);
- }
- main_settings["preload/configurations"] = variations;
-
- Vector<String> langs_enabled;
- Vector<String> langs_disabled;
- for (TreeItem *lang_item = lang_list_root->get_first_child(); lang_item; lang_item = lang_item->get_next()) {
- bool selected = lang_item->is_checked(0);
- String name = lang_item->get_text(1);
- if (selected) {
- langs_enabled.push_back(name);
- } else {
- langs_disabled.push_back(name);
+ preload_config[E.key] = E.value;
}
- }
- main_settings["support_overrides/language_enabled"] = langs_enabled;
- main_settings["support_overrides/language_disabled"] = langs_disabled;
-
- Vector<String> scripts_enabled;
- Vector<String> scripts_disabled;
- for (TreeItem *script_item = script_list_root->get_first_child(); script_item; script_item = script_item->get_next()) {
- bool selected = script_item->is_checked(0);
- String name = script_item->get_text(1);
- if (selected) {
- scripts_enabled.push_back(name);
- } else {
- scripts_disabled.push_back(name);
- }
- }
- main_settings["support_overrides/script_enabled"] = scripts_enabled;
- main_settings["support_overrides/script_disabled"] = scripts_disabled;
-
- if (!selected_chars.is_empty()) {
- Vector<String> ranges;
- char32_t start = selected_chars.front()->get();
- for (RBSet<char32_t>::Element *E = selected_chars.front()->next(); E; E = E->next()) {
- if (E->prev() && ((E->prev()->get() + 1) != E->get())) {
- ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(E->prev()->get(), 16));
- start = E->get();
- }
+
+ Array chars;
+ for (const char32_t &E : import_variation_data->selected_chars) {
+ chars.push_back(E);
}
- ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(selected_chars.back()->get(), 16));
- main_settings["preload/char_ranges"] = ranges;
- }
+ preload_config["chars"] = chars;
- if (!selected_glyphs.is_empty()) {
- Vector<String> ranges;
- int32_t start = selected_glyphs.front()->get();
- for (RBSet<int32_t>::Element *E = selected_glyphs.front()->next(); E; E = E->next()) {
- if (E->prev() && ((E->prev()->get() + 1) != E->get())) {
- ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(E->prev()->get(), 16));
- start = E->get();
- }
+ Array glyphs;
+ for (const int32_t &E : import_variation_data->selected_glyphs) {
+ glyphs.push_back(E);
}
- ranges.push_back(String("0x") + String::num_int64(start, 16) + String("-0x") + String::num_int64(selected_glyphs.back()->get(), 16));
- main_settings["preload/glyph_ranges"] = ranges;
- }
+ preload_config["glyphs"] = glyphs;
- Dictionary ot_ov;
- for (TreeItem *ot_item = ot_list_root->get_first_child(); ot_item; ot_item = ot_item->get_next()) {
- String tag = ot_item->get_text(0);
- int32_t value = ot_item->get_text(1).to_int();
- ot_ov[tag] = value;
+ configurations.push_back(preload_config);
}
- main_settings["opentype_feature_overrides"] = ot_ov;
+ main_settings["preload"] = configurations;
+ main_settings["language_support"] = import_settings_data->get("language_support");
+ main_settings["script_support"] = import_settings_data->get("script_support");
+ main_settings["opentype_features"] = import_settings_data->get("opentype_features");
if (OS::get_singleton()->is_stdout_verbose()) {
print_line("Import settings:");
@@ -1058,33 +939,33 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
// Load font for preview.
- Ref<FontData> dfont_prev;
- dfont_prev.instantiate();
- dfont_prev->set_data(data);
-
font_preview.instantiate();
- font_preview->add_data(dfont_prev);
+ font_preview->set_data(data);
+ String font_name = vformat("%s (%s)", font_preview->get_font_name(), font_preview->get_font_style_name());
String sample;
static const String sample_base = U"12漢字ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš áœ€áœ á€á áž€á  á¤á¥Ab😀";
for (int i = 0; i < sample_base.length(); i++) {
- if (dfont_prev->has_char(sample_base[i])) {
+ if (font_preview->has_char(sample_base[i])) {
sample += sample_base[i];
}
}
if (sample.is_empty()) {
- sample = dfont_prev->get_supported_chars().substr(0, 6);
+ sample = font_preview->get_supported_chars().substr(0, 6);
}
font_preview_label->set_text(sample);
- // Load second copy of font with MSDF disabled for the glyph table and metadata extraction.
- Ref<FontData> dfont_main;
- dfont_main.instantiate();
- dfont_main->set_data(data);
- dfont_main->set_multichannel_signed_distance_field(false);
+ Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ if (bold_font.is_valid() && bold_font.is_valid()) {
+ font_name_label->add_theme_font_override("bold_font", bold_font);
+ }
+ font_name_label->set_text(font_name);
+ // Load second copy of font with MSDF disabled for the glyph table and metadata extraction.
font_main.instantiate();
- font_main->add_data(dfont_main);
+ font_main->set_data(data);
+ font_main->set_multichannel_signed_distance_field(false);
+
text_edit->add_theme_font_override("font", font_main);
base_path = p_path;
@@ -1092,35 +973,27 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
inspector_vars->edit(nullptr);
inspector_general->edit(nullptr);
- int gww = get_theme_font(SNAME("font"))->get_string_size("00000", get_theme_font_size(SNAME("font_size"))).x + 50;
+ text_settings_data.instantiate();
+ ERR_FAIL_NULL(text_settings_data);
+
+ text_settings_data->owner = this;
+
+ for (List<ResourceImporter::ImportOption>::Element *F = options_text.front(); F; F = F->next()) {
+ text_settings_data->defaults[F->get().option.name] = F->get().default_value;
+ }
+
+ text_settings_data->fd = font_main;
+ text_settings_data->options = options_text;
+
+ inspector_text->edit(text_settings_data.ptr());
+
+ int gww = get_theme_font(SNAME("font"))->get_string_size("00000").x + 50;
glyph_table->set_column_custom_minimum_width(0, gww);
glyph_table->clear();
vars_list->clear();
- lang_list->clear();
- script_list->clear();
- ot_list->clear();
-
- selected_chars.clear();
- selected_glyphs.clear();
- text_edit->set_text(String());
vars_list_root = vars_list->create_item();
- lang_list_root = lang_list->create_item();
- script_list_root = script_list->create_item();
- ot_list_root = ot_list->create_item();
-
- options_variations.clear();
- Dictionary var_list = dfont_main->get_supported_variation_list();
- for (int i = 0; i < var_list.size(); i++) {
- int32_t tag = var_list.get_key_at_index(i);
- Vector3i value = var_list.get_value_at_index(i);
- options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, TS->tag_to_name(tag), PROPERTY_HINT_RANGE, itos(value.x) + "," + itos(value.y) + ",1"), value.z));
- }
- options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_RANGE, "0,127,1"), 16));
- options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1"), 0));
- options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "extra_spacing_glyph"), 0));
- options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "extra_spacing_space"), 0));
import_settings_data->defaults.clear();
for (List<ResourceImporter::ImportOption>::Element *E = options_general.front(); E; E = E->next()) {
@@ -1139,157 +1012,58 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
for (List<String>::Element *E = keys.front(); E; E = E->next()) {
String key = E->get();
print_verbose(String(" ") + key + " == " + String(config->get_value("params", key)));
- if (key == "preload/char_ranges") {
- Vector<String> ranges = config->get_value("params", key);
- for (int i = 0; i < ranges.size(); i++) {
- int32_t start, end;
- Vector<String> tokens = ranges[i].split("-");
- if (tokens.size() == 2) {
- if (!ResourceImporterDynamicFont::_decode_range(tokens[0], start) || !ResourceImporterDynamicFont::_decode_range(tokens[1], end)) {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- } else if (tokens.size() == 1) {
- if (!ResourceImporterDynamicFont::_decode_range(tokens[0], start)) {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- end = start;
- } else {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- for (int32_t j = start; j <= end; j++) {
- selected_chars.insert(j);
- }
- }
- } else if (key == "preload/glyph_ranges") {
- Vector<String> ranges = config->get_value("params", key);
- for (int i = 0; i < ranges.size(); i++) {
- int32_t start, end;
- Vector<String> tokens = ranges[i].split("-");
- if (tokens.size() == 2) {
- if (!ResourceImporterDynamicFont::_decode_range(tokens[0], start) || !ResourceImporterDynamicFont::_decode_range(tokens[1], end)) {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- } else if (tokens.size() == 1) {
- if (!ResourceImporterDynamicFont::_decode_range(tokens[0], start)) {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- end = start;
- } else {
- WARN_PRINT("Invalid range: \"" + ranges[i] + "\"");
- continue;
- }
- for (int32_t j = start; j <= end; j++) {
- selected_glyphs.insert(j);
- }
- }
- } else if (key == "preload/configurations") {
- Vector<String> variations = config->get_value("params", key);
- for (int i = 0; i < variations.size(); i++) {
+ if (key == "preload") {
+ Array preload_configurations = config->get_value("params", key);
+ for (int i = 0; i < preload_configurations.size(); i++) {
+ Dictionary preload_config = preload_configurations[i];
+
+ Dictionary variation = preload_config.has("variation_opentype") ? preload_config["variation_opentype"].operator Dictionary() : Dictionary();
+ double embolden = preload_config.has("variation_embolden") ? preload_config["variation_embolden"].operator double() : 0;
+ int face_index = preload_config.has("variation_face_index") ? preload_config["variation_face_index"].operator int() : 0;
+ Transform2D transform = preload_config.has("variation_transform") ? preload_config["variation_transform"].operator Transform2D() : Transform2D();
+ Vector2i size = preload_config.has("size") ? preload_config["size"].operator Vector2i() : Vector2i(16, 0);
+ String cfg_name = preload_config.has("name") ? preload_config["name"].operator String() : vformat("Configuration %d", i);
+
TreeItem *vars_item = vars_list->create_item(vars_list_root);
ERR_FAIL_NULL(vars_item);
- vars_item->set_text(0, TTR("Configuration") + " " + itos(i));
+ vars_item->set_text(0, cfg_name);
vars_item->set_editable(0, true);
vars_item->add_button(1, vars_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove Variation"));
vars_item->set_button_color(1, 0, Color(1, 1, 1, 0.75));
Ref<DynamicFontImportSettingsData> import_variation_data_custom;
import_variation_data_custom.instantiate();
- import_variation_data_custom->owner = this;
ERR_FAIL_NULL(import_variation_data_custom);
+ import_variation_data_custom->owner = this;
for (List<ResourceImporter::ImportOption>::Element *F = options_variations.front(); F; F = F->next()) {
import_variation_data_custom->defaults[F->get().option.name] = F->get().default_value;
}
- import_variation_data_custom->options = options_variations;
+ import_variation_data_custom->fd = font_main;
+ import_variation_data_custom->options = options_variations;
vars_item->set_metadata(0, import_variation_data_custom);
- Vector<String> variation_tags = variations[i].split(",");
- for (int j = 0; j < variation_tags.size(); j++) {
- Vector<String> tokens = variation_tags[j].split("=");
- if (tokens[0] == "name") {
- vars_item->set_text(0, tokens[1]);
- } else if (tokens[0] == "size" || tokens[0] == "outline_size" || tokens[0] == "extra_spacing_space" || tokens[0] == "extra_spacing_glyph") {
- import_variation_data_custom->set(tokens[0], tokens[1].to_int());
- } else {
- import_variation_data_custom->set(tokens[0], tokens[1].to_float());
- }
+
+ import_variation_data_custom->set("size", size.x);
+ import_variation_data_custom->set("outline_size", size.y);
+ import_variation_data_custom->set("variation_opentype", variation);
+ import_variation_data_custom->set("variation_embolden", embolden);
+ import_variation_data_custom->set("variation_face_index", face_index);
+ import_variation_data_custom->set("variation_transform", transform);
+
+ Array chars = preload_config["chars"];
+ for (int j = 0; j < chars.size(); j++) {
+ char32_t c = chars[j].operator int();
+ import_variation_data_custom->selected_chars.insert(c);
}
- }
- } else if (key == "support_overrides/language_enabled") {
- PackedStringArray _langs = config->get_value("params", key);
- for (int i = 0; i < _langs.size(); i++) {
- TreeItem *lang_item = lang_list->create_item(lang_list_root);
- ERR_FAIL_NULL(lang_item);
-
- lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- lang_item->set_editable(0, true);
- lang_item->set_checked(0, true);
- lang_item->set_text(1, _langs[i]);
- lang_item->set_editable(1, true);
- lang_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- }
- } else if (key == "support_overrides/language_disabled") {
- PackedStringArray _langs = config->get_value("params", key);
- for (int i = 0; i < _langs.size(); i++) {
- TreeItem *lang_item = lang_list->create_item(lang_list_root);
- ERR_FAIL_NULL(lang_item);
-
- lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- lang_item->set_editable(0, true);
- lang_item->set_checked(0, false);
- lang_item->set_text(1, _langs[i]);
- lang_item->set_editable(1, true);
- lang_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- }
- } else if (key == "support_overrides/script_enabled") {
- PackedStringArray _scripts = config->get_value("params", key);
- for (int i = 0; i < _scripts.size(); i++) {
- TreeItem *script_item = script_list->create_item(script_list_root);
- ERR_FAIL_NULL(script_item);
-
- script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- script_item->set_editable(0, true);
- script_item->set_checked(0, true);
- script_item->set_text(1, _scripts[i]);
- script_item->set_editable(1, true);
- script_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- }
- } else if (key == "support_overrides/script_disabled") {
- PackedStringArray _scripts = config->get_value("params", key);
- for (int i = 0; i < _scripts.size(); i++) {
- TreeItem *script_item = script_list->create_item(script_list_root);
- ERR_FAIL_NULL(script_item);
-
- script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- script_item->set_editable(0, true);
- script_item->set_checked(0, false);
- script_item->set_text(1, _scripts[i]);
- script_item->set_editable(1, true);
- script_item->add_button(2, lang_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- }
- } else if (key == "opentype_feature_overrides") {
- Dictionary features = config->get_value("params", key);
- for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) {
- TreeItem *ot_item = ot_list->create_item(ot_list_root);
- ERR_FAIL_NULL(ot_item);
- int32_t value = features[*ftr];
- if (ftr->get_type() == Variant::STRING) {
- ot_item->set_text(0, *ftr);
- } else {
- ot_item->set_text(0, TS->tag_to_name(*ftr));
+
+ Array glyphs = preload_config["glyphs"];
+ for (int j = 0; j < glyphs.size(); j++) {
+ int32_t c = glyphs[j];
+ import_variation_data_custom->selected_glyphs.insert(c);
}
- ot_item->set_editable(0, false);
- ot_item->set_text(1, itos(value));
- ot_item->set_editable(1, true);
- ot_item->add_button(2, ot_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_VAR, false, TTR("Remove"));
- ot_item->set_button_color(2, 0, Color(1, 1, 1, 0.75));
}
} else {
Variant value = config->get_value("params", key);
@@ -1297,61 +1071,26 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
}
}
}
- label_glyphs->set_text(TTR("Preloaded glyphs:") + " " + itos(selected_glyphs.size()));
+ import_settings_data->fd = font_main;
import_settings_data->options = options_general;
inspector_general->edit(import_settings_data.ptr());
import_settings_data->notify_property_list_changed();
- if (font_preview->get_data_count() > 0) {
- font_preview->get_data(0)->set_face_index(import_settings_data->get("face_index"));
- font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased"));
- font_preview->get_data(0)->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
- font_preview->get_data(0)->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
- font_preview->get_data(0)->set_msdf_size(import_settings_data->get("msdf_size"));
- font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
- font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
- font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
- font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
- font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
- font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
+ if (font_preview.is_valid()) {
+ font_preview->set_antialiased(import_settings_data->get("antialiased"));
+ font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
+ font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range"));
+ font_preview->set_msdf_size(import_settings_data->get("msdf_size"));
+ font_preview->set_force_autohinter(import_settings_data->get("force_autohinter"));
+ font_preview->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
+ font_preview->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
+ font_preview->set_oversampling(import_settings_data->get("oversampling"));
}
font_preview_label->add_theme_font_override("font", font_preview);
+ font_preview_label->add_theme_font_size_override("font_size", 200 * EDSCALE);
font_preview_label->update();
- menu_ot->clear();
- menu_ot_ss->clear();
- menu_ot_cv->clear();
- menu_ot_cu->clear();
- bool have_ss = false;
- bool have_cv = false;
- bool have_cu = false;
- Dictionary features = font_preview->get_feature_list();
- for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) {
- String ftr_name = TS->tag_to_name(*ftr);
- if (ftr_name.begins_with("stylistic_set_")) {
- menu_ot_ss->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- have_ss = true;
- } else if (ftr_name.begins_with("character_variant_")) {
- menu_ot_cv->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- have_cv = true;
- } else if (ftr_name.begins_with("custom_")) {
- menu_ot_cu->add_item(ftr_name.replace("custom_", ""), (int32_t)*ftr);
- have_cu = true;
- } else {
- menu_ot->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- }
- }
- if (have_ss) {
- menu_ot->add_submenu_item(RTR("Stylistic Sets"), "SSMenu");
- }
- if (have_cv) {
- menu_ot->add_submenu_item(RTR("Character Variants"), "CVMenu");
- }
- if (have_cu) {
- menu_ot->add_submenu_item(RTR("Custom"), "CUMenu");
- }
-
_variations_validate();
popup_centered_ratio();
@@ -1366,7 +1105,8 @@ DynamicFontImportSettings *DynamicFontImportSettings::get_singleton() {
DynamicFontImportSettings::DynamicFontImportSettings() {
singleton = this;
- options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "face_index"), 0));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
@@ -1375,44 +1115,29 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
- options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
- options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
- options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));
-
- // Popup menus
-
- locale_select = memnew(EditorLocaleDialog);
- locale_select->connect("locale_selected", callable_mp(this, &DynamicFontImportSettings::_lang_add_item));
- add_child(locale_select);
- menu_scripts = memnew(PopupMenu);
- menu_scripts->set_name("Script");
- script_codes = TranslationServer::get_singleton()->get_all_scripts();
- for (int i = 0; i < script_codes.size(); i++) {
- menu_scripts->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i);
- }
- add_child(menu_scripts);
- menu_scripts->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_script_add_item));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Metadata Overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "language_support"), Dictionary()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "script_support"), Dictionary()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_features"), Dictionary()));
- menu_ot = memnew(PopupMenu);
- add_child(menu_ot);
- menu_ot->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Fallbacks", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
- menu_ot_cv = memnew(PopupMenu);
- menu_ot_cv->set_name("CVMenu");
- menu_ot->add_child(menu_ot_cv);
- menu_ot_cv->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));
- menu_ot_ss = memnew(PopupMenu);
- menu_ot_ss->set_name("SSMenu");
- menu_ot->add_child(menu_ot_ss);
- menu_ot_ss->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item));
+ options_text.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_features"), Dictionary()));
+ options_text.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), ""));
- menu_ot_cu = memnew(PopupMenu);
- menu_ot_cu->set_name("CUMenu");
- menu_ot->add_child(menu_ot_cu);
- menu_ot_cu->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add_item));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_RANGE, "0,127,1"), 16));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1"), 0));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Variation", PROPERTY_HINT_NONE, "variation", PROPERTY_USAGE_GROUP), Variant()));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::DICTIONARY, "variation_opentype"), Dictionary()));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "variation_embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "variation_face_index"), 0));
+ options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "variation_transform"), Transform2D()));
Color warn_color = (EditorNode::get_singleton()) ? EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")) : Color(1, 1, 0);
@@ -1442,7 +1167,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
main_pages->add_child(page1_vb);
page1_description = memnew(Label);
- page1_description->set_text(TTR("Select font rendering options:"));
+ page1_description->set_text(TTR("Select font rendering options, fallback font, and metadata override:"));
page1_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
page1_vb->add_child(page1_description);
@@ -1451,15 +1176,25 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
page1_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
page1_vb->add_child(page1_hb);
+ VBoxContainer *page1_lbl_vb = memnew(VBoxContainer);
+ page1_lbl_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ page1_lbl_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page1_hb->add_child(page1_lbl_vb);
+
+ font_name_label = memnew(Label);
+ font_name_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ font_name_label->set_clip_text(true);
+ font_name_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page1_lbl_vb->add_child(font_name_label);
+
font_preview_label = memnew(Label);
- font_preview_label->add_theme_font_size_override("font_size", 200 * EDSCALE);
font_preview_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
font_preview_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
font_preview_label->set_autowrap_mode(TextServer::AUTOWRAP_ARBITRARY);
font_preview_label->set_clip_text(true);
font_preview_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
font_preview_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page1_hb->add_child(font_preview_label);
+ page1_lbl_vb->add_child(font_preview_label);
inspector_general = memnew(EditorInspector);
inspector_general->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1469,11 +1204,11 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
// Page 2 layout: Configurations
VBoxContainer *page2_vb = memnew(VBoxContainer);
- page2_vb->set_name(TTR("Sizes and Variations"));
+ page2_vb->set_name(TTR("Pre-render configurations"));
main_pages->add_child(page2_vb);
page2_description = memnew(Label);
- page2_description->set_text(TTR("Add font size, variation coordinates, and extra spacing combinations to pre-render:"));
+ page2_description->set_text(TTR("Add font size, and variation coordinates, and select glyphs to pre-render:"));
page2_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
page2_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
page2_vb->add_child(page2_description);
@@ -1517,48 +1252,44 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
inspector_vars = memnew(EditorInspector);
inspector_vars->set_v_size_flags(Control::SIZE_EXPAND_FILL);
inspector_vars->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_variation_changed));
- page2_hb->add_child(inspector_vars);
-
- // Page 3 layout: Text to select glyphs
- VBoxContainer *page3_vb = memnew(VBoxContainer);
- page3_vb->set_name(TTR("Glyphs from the Text"));
- main_pages->add_child(page3_vb);
+ page2_side_vb->add_child(inspector_vars);
- page3_description = memnew(Label);
- page3_description->set_text(TTR("Enter a text to shape and add all required glyphs to pre-render list:"));
- page3_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page3_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
- page3_vb->add_child(page3_description);
+ preload_pages = memnew(TabContainer);
+ preload_pages->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
+ preload_pages->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ preload_pages->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_hb->add_child(preload_pages);
- HBoxContainer *ot_hb = memnew(HBoxContainer);
- page3_vb->add_child(ot_hb);
- ot_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ // Page 2.1 layout: Text to select glyphs
+ VBoxContainer *page2_1_vb = memnew(VBoxContainer);
+ page2_1_vb->set_name(TTR("Glyphs from the Text"));
+ preload_pages->add_child(page2_1_vb);
- Label *label_ed_ftr = memnew(Label);
- ot_hb->add_child(label_ed_ftr);
- label_ed_ftr->set_text(TTR("OpenType features:"));
+ page2_1_description = memnew(Label);
+ page2_1_description->set_text(TTR("Enter a text to shape and add all required glyphs to pre-render list:"));
+ page2_1_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_1_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ page2_1_vb->add_child(page2_1_description);
- ftr_edit = memnew(LineEdit);
- ot_hb->add_child(ftr_edit);
- ftr_edit->connect("text_changed", callable_mp(this, &DynamicFontImportSettings::_change_text_opts));
- ftr_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ HSplitContainer *page2_1_hb = memnew(HSplitContainer);
+ page2_1_vb->add_child(page2_1_hb);
+ page2_1_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_1_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- Label *label_ed_lang = memnew(Label);
- ot_hb->add_child(label_ed_lang);
- label_ed_lang->set_text(TTR("Text language:"));
+ inspector_text = memnew(EditorInspector);
- lang_edit = memnew(LineEdit);
- ot_hb->add_child(lang_edit);
- lang_edit->connect("text_changed", callable_mp(this, &DynamicFontImportSettings::_change_text_opts));
- lang_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ inspector_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ inspector_text->set_custom_minimum_size(Size2(300 * EDSCALE, 250 * EDSCALE));
+ inspector_text->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_change_text_opts));
+ page2_1_hb->add_child(inspector_text);
text_edit = memnew(TextEdit);
- page3_vb->add_child(text_edit);
+ page2_1_hb->add_child(text_edit);
text_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
text_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
HBoxContainer *text_hb = memnew(HBoxContainer);
- page3_vb->add_child(text_hb);
+ page2_1_vb->add_child(text_hb);
text_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
label_glyphs = memnew(Label);
@@ -1576,21 +1307,21 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
btn_clear->set_text(TTR("Clear glyph list"));
btn_clear->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_glyph_clear));
- // Page 4 layout: Character map
- VBoxContainer *page4_vb = memnew(VBoxContainer);
- page4_vb->set_name(TTR("Glyphs from the Character Map"));
- main_pages->add_child(page4_vb);
+ // Page 2.2 layout: Character map
+ VBoxContainer *page2_2_vb = memnew(VBoxContainer);
+ page2_2_vb->set_name(TTR("Glyphs from the Character Map"));
+ preload_pages->add_child(page2_2_vb);
- page4_description = memnew(Label);
- page4_description->set_text(TTR("Add or remove additional glyphs from the character map to pre-render list:\nNote: Some stylistic alternatives and glyph variants do not have one-to-one correspondence to character, and not shown in this map, use \"Glyphs from the text\" to add these."));
- page4_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page4_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
- page4_vb->add_child(page4_description);
+ page2_2_description = memnew(Label);
+ page2_2_description->set_text(TTR("Add or remove glyphs from the character map to pre-render list:\nNote: Some stylistic alternatives and glyph variants do not have one-to-one correspondence to character, and not shown in this map, use \"Glyphs from the text\" tab to add these."));
+ page2_2_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ page2_2_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
+ page2_2_vb->add_child(page2_2_description);
HSplitContainer *glyphs_split = memnew(HSplitContainer);
glyphs_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
glyphs_split->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page4_vb->add_child(glyphs_split);
+ page2_2_vb->add_child(glyphs_split);
glyph_table = memnew(Tree);
glyphs_split->add_child(glyph_table);
@@ -1627,101 +1358,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
_add_glyph_range_item(unicode_ranges[i].start, unicode_ranges[i].end, unicode_ranges[i].name);
}
- // Page 4 layout: Metadata override
- VBoxContainer *page5_vb = memnew(VBoxContainer);
- page5_vb->set_name(TTR("Metadata Override"));
- main_pages->add_child(page5_vb);
-
- page5_description = memnew(Label);
- page5_description->set_text(TTR("Add or remove language and script support overrides, to control fallback font selection order:"));
- page5_description->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- page5_description->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
- page5_vb->add_child(page5_description);
-
- HBoxContainer *hb_lang = memnew(HBoxContainer);
- page5_vb->add_child(hb_lang);
-
- label_langs = memnew(Label);
- label_langs->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- label_langs->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- label_langs->set_text(TTR("Language support overrides"));
- hb_lang->add_child(label_langs);
-
- add_lang = memnew(Button);
- hb_lang->add_child(add_lang);
- add_lang->set_tooltip(TTR("Add language override"));
- add_lang->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- add_lang->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_lang_add));
-
- lang_list = memnew(Tree);
- page5_vb->add_child(lang_list);
- lang_list->set_hide_root(true);
- lang_list->set_columns(3);
- lang_list->set_column_expand(0, false); // Check
- lang_list->set_column_custom_minimum_width(0, 50 * EDSCALE);
- lang_list->set_column_expand(1, true);
- lang_list->set_column_custom_minimum_width(1, 80 * EDSCALE);
- lang_list->set_column_expand(2, false);
- lang_list->set_column_custom_minimum_width(2, 50 * EDSCALE);
- lang_list->connect("button_clicked", callable_mp(this, &DynamicFontImportSettings::_lang_remove));
- lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- HBoxContainer *hb_script = memnew(HBoxContainer);
- page5_vb->add_child(hb_script);
-
- label_script = memnew(Label);
- label_script->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- label_script->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- label_script->set_text(TTR("Script support overrides"));
- hb_script->add_child(label_script);
-
- add_script = memnew(Button);
- hb_script->add_child(add_script);
- add_script->set_tooltip(TTR("Add script override"));
- add_script->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- add_script->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_script_add));
-
- script_list = memnew(Tree);
- page5_vb->add_child(script_list);
- script_list->set_hide_root(true);
- script_list->set_columns(3);
- script_list->set_column_expand(0, false);
- script_list->set_column_custom_minimum_width(0, 50 * EDSCALE);
- script_list->set_column_expand(1, true);
- script_list->set_column_custom_minimum_width(1, 80 * EDSCALE);
- script_list->set_column_expand(2, false);
- script_list->set_column_custom_minimum_width(2, 50 * EDSCALE);
- script_list->connect("button_clicked", callable_mp(this, &DynamicFontImportSettings::_script_remove));
- script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- HBoxContainer *hb_ot = memnew(HBoxContainer);
- page5_vb->add_child(hb_ot);
-
- label_ot = memnew(Label);
- label_ot->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- label_ot->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- label_ot->set_text(TTR("OpenType feature overrides"));
- hb_ot->add_child(label_ot);
-
- add_ot = memnew(Button);
- hb_ot->add_child(add_ot);
- add_ot->set_tooltip(TTR("Add feature override"));
- add_ot->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- add_ot->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_ot_add));
-
- ot_list = memnew(Tree);
- page5_vb->add_child(ot_list);
- ot_list->set_hide_root(true);
- ot_list->set_columns(3);
- ot_list->set_column_expand(0, true);
- ot_list->set_column_custom_minimum_width(0, 80 * EDSCALE);
- ot_list->set_column_expand(1, true);
- ot_list->set_column_custom_minimum_width(1, 80 * EDSCALE);
- ot_list->set_column_expand(2, false);
- ot_list->set_column_custom_minimum_width(2, 50 * EDSCALE);
- ot_list->connect("button_clicked", callable_mp(this, &DynamicFontImportSettings::_ot_remove));
- ot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
// Common
import_settings_data.instantiate();
diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h
index ba75c98057..a1f763b445 100644
--- a/editor/import/dynamic_font_import_settings.h
+++ b/editor/import/dynamic_font_import_settings.h
@@ -45,7 +45,30 @@
#include "scene/resources/font.h"
#include "servers/text_server.h"
-class DynamicFontImportSettingsData;
+class DynamicFontImportSettings;
+
+class DynamicFontImportSettingsData : public RefCounted {
+ GDCLASS(DynamicFontImportSettingsData, RefCounted)
+ friend class DynamicFontImportSettings;
+
+ HashMap<StringName, Variant> settings;
+ HashMap<StringName, Variant> defaults;
+ List<ResourceImporter::ImportOption> options;
+ DynamicFontImportSettings *owner = nullptr;
+
+ HashSet<char32_t> selected_chars;
+ HashSet<int32_t> selected_glyphs;
+
+ Ref<FontFile> fd;
+
+public:
+ 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;
+
+ Ref<FontFile> get_font() const;
+};
+
class EditorFileDialog;
class EditorInspector;
class EditorLocaleDialog;
@@ -67,21 +90,19 @@ class DynamicFontImportSettings : public ConfirmationDialog {
List<ResourceImporter::ImportOption> options_variations;
List<ResourceImporter::ImportOption> options_general;
- EditorLocaleDialog *locale_select = nullptr;
- Vector<String> script_codes;
-
// Root layout
Label *label_warn = nullptr;
TabContainer *main_pages = nullptr;
// Page 1 layout: Rendering Options
Label *page1_description = nullptr;
+ Label *font_name_label = nullptr;
Label *font_preview_label = nullptr;
EditorInspector *inspector_general = nullptr;
void _main_prop_changed(const String &p_edited_property);
- // Page 2 layout: Configurations
+ // Page 2 layout: Preload Configurations
Label *page2_description = nullptr;
Label *label_vars = nullptr;
Button *add_var = nullptr;
@@ -95,19 +116,23 @@ class DynamicFontImportSettings : public ConfirmationDialog {
void _variation_changed(const String &p_edited_property);
void _variations_validate();
- // Page 3 layout: Text to select glyphs
- Label *page3_description = nullptr;
+ TabContainer *preload_pages = nullptr;
+
+ // Page 2.1 layout: Text to select glyphs
+ Label *page2_1_description = nullptr;
Label *label_glyphs = nullptr;
TextEdit *text_edit = nullptr;
- LineEdit *ftr_edit = nullptr;
- LineEdit *lang_edit = nullptr;
+ EditorInspector *inspector_text = nullptr;
+
+ List<ResourceImporter::ImportOption> options_text;
+ Ref<DynamicFontImportSettingsData> text_settings_data;
void _change_text_opts();
void _glyph_text_selected();
void _glyph_clear();
- // Page 4 layout: Character map
- Label *page4_description = nullptr;
+ // Page 2.2 layout: Character map
+ Label *page2_2_description = nullptr;
Tree *glyph_table = nullptr;
Tree *glyph_tree = nullptr;
TreeItem *glyph_root = nullptr;
@@ -119,51 +144,12 @@ class DynamicFontImportSettings : public ConfirmationDialog {
bool _char_update(int32_t p_char);
void _range_update(int32_t p_start, int32_t p_end);
- // Page 5 layout: Metadata override
- Label *page5_description = nullptr;
- Button *add_lang = nullptr;
- Button *add_script = nullptr;
- Button *add_ot = nullptr;
-
- PopupMenu *menu_scripts = nullptr;
- PopupMenu *menu_ot = nullptr;
- PopupMenu *menu_ot_ss = nullptr;
- PopupMenu *menu_ot_cv = nullptr;
- PopupMenu *menu_ot_cu = nullptr;
-
- Tree *lang_list = nullptr;
- TreeItem *lang_list_root = nullptr;
- Label *label_langs = nullptr;
-
- Tree *script_list = nullptr;
- TreeItem *script_list_root = nullptr;
- Label *label_script = nullptr;
-
- Tree *ot_list = nullptr;
- TreeItem *ot_list_root = nullptr;
- Label *label_ot = nullptr;
-
- void _lang_add();
- void _lang_add_item(const String &p_locale);
- void _lang_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
-
- void _script_add();
- void _script_add_item(int p_option);
- void _script_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
-
- void _ot_add();
- void _ot_add_item(int p_option);
- void _ot_remove(Object *p_item, int p_column, int p_id, MouseButton p_button);
-
// Common
void _add_glyph_range_item(int32_t p_start, int32_t p_end, const String &p_name);
- Ref<Font> font_preview;
- Ref<Font> font_main;
-
- RBSet<char32_t> selected_chars;
- RBSet<int32_t> selected_glyphs;
+ Ref<FontFile> font_preview;
+ Ref<FontFile> font_main;
void _re_import();
diff --git a/editor/import/post_import_plugin_skeleton_renamer.cpp b/editor/import/post_import_plugin_skeleton_renamer.cpp
new file mode 100644
index 0000000000..b0c4bc8c30
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_renamer.cpp
@@ -0,0 +1,144 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_renamer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "post_import_plugin_skeleton_renamer.h"
+
+#include "editor/import/scene_import_settings.h"
+#include "scene/3d/importer_mesh_instance_3d.h"
+#include "scene/3d/skeleton_3d.h"
+#include "scene/animation/animation_player.h"
+#include "scene/resources/bone_map.h"
+
+void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) {
+ if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
+ r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones"), true));
+ }
+}
+
+void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) {
+ if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
+ // Prepare objects.
+ Object *map = p_options["retarget/bone_map"].get_validated_object();
+ if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
+ return;
+ }
+ BoneMap *bone_map = Object::cast_to<BoneMap>(map);
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
+
+ // Rename bones in Skeleton3D.
+ {
+ int len = skeleton->get_bone_count();
+ for (int i = 0; i < len; i++) {
+ StringName bn = bone_map->find_profile_bone_name(skeleton->get_bone_name(i));
+ if (bn) {
+ skeleton->set_bone_name(i, bn);
+ }
+ }
+ }
+
+ // Rename bones in Skin.
+ {
+ TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
+ while (nodes.size()) {
+ ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
+ Ref<Skin> skin = mi->get_skin();
+ if (skin.is_valid()) {
+ Node *node = mi->get_node(mi->get_skeleton_path());
+ if (node) {
+ Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (mesh_skeleton && node == skeleton) {
+ int len = skin->get_bind_count();
+ for (int i = 0; i < len; i++) {
+ StringName bn = bone_map->find_profile_bone_name(skin->get_bind_name(i));
+ if (bn) {
+ skin->set_bind_name(i, bn);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Rename bones in AnimationPlayer.
+ {
+ TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
+ while (nodes.size()) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (const StringName &name : anims) {
+ Ref<Animation> anim = ap->get_animation(name);
+ int len = anim->get_track_count();
+ for (int i = 0; i < len; i++) {
+ if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) {
+ continue;
+ }
+ String track_path = String(anim->track_get_path(i).get_concatenated_names());
+ Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
+ if (node) {
+ Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
+ if (track_skeleton && track_skeleton == skeleton) {
+ StringName bn = bone_map->find_profile_bone_name(anim->track_get_path(i).get_subname(0));
+ if (bn) {
+ anim->track_set_path(i, track_path + ":" + bn);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Rename bones in all Nodes by calling method.
+ {
+ Vector<Variant> vargs;
+ vargs.push_back(p_base_scene);
+ vargs.push_back(skeleton);
+ vargs.push_back(bone_map);
+ const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * vargs.size());
+ const Variant *args = vargs.ptr();
+ uint32_t argcount = vargs.size();
+ for (uint32_t i = 0; i < argcount; i++) {
+ argptrs[i] = &args[i];
+ }
+
+ TypedArray<Node> nodes = p_base_scene->find_children("*");
+ while (nodes.size()) {
+ Node *nd = Object::cast_to<Node>(nodes.pop_back());
+ Callable::CallError ce;
+ nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce);
+ }
+ }
+ }
+}
+
+PostImportPluginSkeletonRenamer::PostImportPluginSkeletonRenamer() {
+}
diff --git a/editor/import/post_import_plugin_skeleton_renamer.h b/editor/import/post_import_plugin_skeleton_renamer.h
new file mode 100644
index 0000000000..73cbabd1c5
--- /dev/null
+++ b/editor/import/post_import_plugin_skeleton_renamer.h
@@ -0,0 +1,46 @@
+/*************************************************************************/
+/* post_import_plugin_skeleton_renamer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef POST_IMPORT_PLUGIN_SKELETON_RENAMER_H
+#define POST_IMPORT_PLUGIN_SKELETON_RENAMER_H
+
+#include "resource_importer_scene.h"
+
+class PostImportPluginSkeletonRenamer : public EditorScenePostImportPlugin {
+ GDCLASS(PostImportPluginSkeletonRenamer, EditorScenePostImportPlugin);
+
+public:
+ virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) override;
+ virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) override;
+
+ PostImportPluginSkeletonRenamer();
+};
+
+#endif // POST_IMPORT_PLUGIN_SKELETON_RENAMER_H
diff --git a/editor/import/resource_importer_bmfont.cpp b/editor/import/resource_importer_bmfont.cpp
index 8a40b113b9..987ca4b911 100644
--- a/editor/import/resource_importer_bmfont.cpp
+++ b/editor/import/resource_importer_bmfont.cpp
@@ -52,7 +52,7 @@ String ResourceImporterBMFont::get_save_extension() const {
}
String ResourceImporterBMFont::get_resource_type() const {
- return "FontData";
+ return "FontFile";
}
bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -60,19 +60,25 @@ bool ResourceImporterBMFont::get_option_visibility(const String &p_path, const S
}
void ResourceImporterBMFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
Error ResourceImporterBMFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing BMFont font from: " + p_source_file);
- Ref<FontData> font;
+ Array fallbacks = p_options["fallbacks"];
+
+ Ref<FontFile> font;
font.instantiate();
Error err = font->load_bitmap_font(p_source_file);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load font to file \"" + p_source_file + "\".");
- int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
+ font->set_fallbacks(fallbacks);
+
+ int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index a92b0fe280..f1a70ff30a 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -66,7 +66,7 @@ String ResourceImporterDynamicFont::get_save_extension() const {
}
String ResourceImporterDynamicFont::get_resource_type() const {
- return "FontData";
+ return "FontFile";
}
bool ResourceImporterDynamicFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -103,7 +103,7 @@ String ResourceImporterDynamicFont::get_preset_name(int p_idx) const {
void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
bool msdf = p_preset == PRESET_MSDF;
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "face_index"), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
@@ -114,63 +114,19 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
- r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
- r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides"), Dictionary()));
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/char_ranges"), Vector<String>()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/glyph_ranges"), Vector<String>()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "preload/configurations"), Vector<String>()));
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/language_enabled"), Vector<String>()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/language_disabled"), Vector<String>()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Fallbacks", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/script_enabled"), Vector<String>()));
- r_options->push_back(ImportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "support_overrides/script_disabled"), Vector<String>()));
-}
+ r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
-bool ResourceImporterDynamicFont::_decode_variation(const String &p_token, Dictionary &r_variations, Vector2i &r_size, String &r_name, Vector2i &r_spacing) {
- Vector<String> tokens = p_token.split("=");
- if (tokens.size() == 2) {
- if (tokens[0] == "name") {
- r_name = tokens[1];
- } else if (tokens[0] == "size") {
- r_size.x = tokens[1].to_int();
- } else if (tokens[0] == "outline_size") {
- r_size.y = tokens[1].to_int();
- } else if (tokens[0] == "spacing_space") {
- r_spacing.x = tokens[1].to_int();
- } else if (tokens[0] == "spacing_glyph") {
- r_spacing.y = tokens[1].to_int();
- } else {
- r_variations[tokens[0]] = tokens[1].to_float();
- }
- return true;
- } else {
- WARN_PRINT("Invalid variation: '" + p_token + "'.");
- return false;
- }
-}
-
-bool ResourceImporterDynamicFont::_decode_range(const String &p_token, int32_t &r_pos) {
- if (p_token.begins_with("U+") || p_token.begins_with("u+") || p_token.begins_with("0x")) {
- // Unicode character hex index.
- r_pos = p_token.substr(2).hex_to_int();
- return true;
- } else if (p_token.length() == 3 && p_token[0] == '\'' && p_token[2] == '\'') {
- // Unicode character.
- r_pos = p_token.unicode_at(1);
- return true;
- } else if (p_token.is_numeric()) {
- // Unicode character decimal index.
- r_pos = p_token.to_int();
- return true;
- } else {
- return false;
- }
+ // Hide from the main UI, only for advanced import dialog.
+ r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "preload", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Array()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "language_support", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "script_support", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::DICTIONARY, "opentype_features", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), Dictionary()));
}
bool ResourceImporterDynamicFont::has_advanced_options() const {
@@ -183,30 +139,26 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) {
Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
print_verbose("Importing dynamic font from: " + p_source_file);
- int face_index = p_options["face_index"];
-
bool antialiased = p_options["antialiased"];
bool generate_mipmaps = p_options["generate_mipmaps"];
bool msdf = p_options["multichannel_signed_distance_field"];
int px_range = p_options["msdf_pixel_range"];
int px_size = p_options["msdf_size"];
- Dictionary ot_ov = p_options["opentype_feature_overrides"];
+ Dictionary ot_ov = p_options["opentype_features"];
bool autohinter = p_options["force_autohinter"];
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
- real_t embolden = p_options["embolden"];
- Transform2D transform = p_options["transform"];
+ Array fallbacks = p_options["fallbacks"];
// Load base font data.
Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
// Create font.
- Ref<FontData> font;
+ Ref<FontFile> font;
font.instantiate();
font->set_data(data);
- font->set_face_index(face_index);
font->set_antialiased(antialiased);
font->set_generate_mipmaps(generate_mipmaps);
font->set_multichannel_signed_distance_field(msdf);
@@ -216,105 +168,52 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_fixed_size(0);
font->set_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
- font->set_embolden(embolden);
- font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);
+ font->set_fallbacks(fallbacks);
- Vector<String> lang_en = p_options["support_overrides/language_enabled"];
- for (int i = 0; i < lang_en.size(); i++) {
- font->set_language_support_override(lang_en[i], true);
+ Dictionary langs = p_options["language_support"];
+ for (int i = 0; i < langs.size(); i++) {
+ String key = langs.get_key_at_index(i);
+ bool enabled = langs.get_value_at_index(i);
+ font->set_language_support_override(key, enabled);
}
- Vector<String> lang_dis = p_options["support_overrides/language_disabled"];
- for (int i = 0; i < lang_dis.size(); i++) {
- font->set_language_support_override(lang_dis[i], false);
+ Dictionary scripts = p_options["script_support"];
+ for (int i = 0; i < scripts.size(); i++) {
+ String key = scripts.get_key_at_index(i);
+ bool enabled = scripts.get_value_at_index(i);
+ font->set_script_support_override(key, enabled);
}
- Vector<String> scr_en = p_options["support_overrides/script_enabled"];
- for (int i = 0; i < scr_en.size(); i++) {
- font->set_script_support_override(scr_en[i], true);
- }
+ Array preload_configurations = p_options["preload"];
- Vector<String> scr_dis = p_options["support_overrides/script_disabled"];
- for (int i = 0; i < scr_dis.size(); i++) {
- font->set_script_support_override(scr_dis[i], false);
- }
+ for (int i = 0; i < preload_configurations.size(); i++) {
+ Dictionary preload_config = preload_configurations[i];
- Vector<String> variations = p_options["preload/configurations"];
- Vector<String> char_ranges = p_options["preload/char_ranges"];
- Vector<String> gl_ranges = p_options["preload/glyph_ranges"];
-
- for (int i = 0; i < variations.size(); i++) {
- String name;
- Dictionary var;
- Vector2i size = Vector2(16, 0);
- Vector2i spacing;
-
- Vector<String> variation_tags = variations[i].split(",");
- for (int j = 0; j < variation_tags.size(); j++) {
- if (!_decode_variation(variation_tags[j], var, size, name, spacing)) {
- WARN_PRINT(vformat(TTR("Invalid variation: \"%s\""), variations[i]));
- continue;
- }
- }
- RID conf = font->find_cache(var);
-
- for (int j = 0; j < char_ranges.size(); j++) {
- int32_t start, end;
- Vector<String> tokens = char_ranges[j].split("-");
- if (tokens.size() == 2) {
- if (!_decode_range(tokens[0], start) || !_decode_range(tokens[1], end)) {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
- continue;
- }
- } else if (tokens.size() == 1) {
- if (!_decode_range(tokens[0], start)) {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
- continue;
- }
- end = start;
- } else {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), char_ranges[j]));
- continue;
- }
-
- // Preload character ranges for each variations / sizes.
- print_verbose(vformat(TTR("Pre-rendering range U+%s...%s from configuration \"%s\" (%d / %d)..."), String::num_int64(start, 16), String::num_int64(end, 16), name, i + 1, variations.size()));
- TS->font_render_range(conf, size, start, end);
- }
+ Dictionary variation = preload_config.has("variation_opentype") ? preload_config["variation_opentype"].operator Dictionary() : Dictionary();
+ double embolden = preload_config.has("variation_embolden") ? preload_config["variation_embolden"].operator double() : 0;
+ int face_index = preload_config.has("variation_face_index") ? preload_config["variation_face_index"].operator int() : 0;
+ Transform2D transform = preload_config.has("variation_transform") ? preload_config["variation_transform"].operator Transform2D() : Transform2D();
+ Vector2i size = preload_config.has("size") ? preload_config["size"].operator Vector2i() : Vector2i(16, 0);
+ String name = preload_config.has("name") ? preload_config["name"].operator String() : vformat("Configuration %d", i);
- for (int j = 0; j < gl_ranges.size(); j++) {
- int32_t start, end;
- Vector<String> tokens = gl_ranges[j].split("-");
- if (tokens.size() == 2) {
- if (!_decode_range(tokens[0], start) || !_decode_range(tokens[1], end)) {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
- continue;
- }
- } else if (tokens.size() == 1) {
- if (!_decode_range(tokens[0], start)) {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
- continue;
- }
- end = start;
- } else {
- WARN_PRINT(vformat(TTR("Invalid range: \"%s\""), gl_ranges[j]));
- continue;
- }
-
- // Preload glyph range for each variations / sizes.
- print_verbose(vformat(TTR("Pre-rendering glyph range 0x%s...%s from configuration \"%s\" (%d / %d)..."), String::num_int64(start, 16), String::num_int64(end, 16), name, i + 1, variations.size()));
- for (int32_t k = start; k <= end; k++) {
- TS->font_render_glyph(conf, size, k);
- }
+ RID conf_rid = font->find_variation(variation, face_index, embolden, transform);
+
+ Array chars = preload_config["chars"];
+ for (int j = 0; j < chars.size(); j++) {
+ char32_t c = chars[j].operator int();
+ TS->font_render_range(conf_rid, size, c, c);
}
- TS->font_set_spacing(conf, size.x, TextServer::SPACING_SPACE, spacing.x);
- TS->font_set_spacing(conf, size.x, TextServer::SPACING_GLYPH, spacing.y);
+ Array glyphs = preload_config["glyphs"];
+ for (int j = 0; j < glyphs.size(); j++) {
+ int32_t c = glyphs[j];
+ TS->font_render_glyph(conf_rid, size, c);
+ }
}
- int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
+ int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}
diff --git a/editor/import/resource_importer_dynamic_font.h b/editor/import/resource_importer_dynamic_font.h
index c0b6c094b0..a05c8bab05 100644
--- a/editor/import/resource_importer_dynamic_font.h
+++ b/editor/import/resource_importer_dynamic_font.h
@@ -43,9 +43,6 @@ class ResourceImporterDynamicFont : public ResourceImporter {
};
public:
- static bool _decode_range(const String &p_token, int32_t &r_pos);
- static bool _decode_variation(const String &p_token, Dictionary &r_variations, Vector2i &r_size, String &r_name, Vector2i &r_spacing);
-
virtual String get_importer_name() const override;
virtual String get_visible_name() const override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index 30c349d0f2..ea84d4c883 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -52,7 +52,7 @@ String ResourceImporterImageFont::get_save_extension() const {
}
String ResourceImporterImageFont::get_resource_type() const {
- return "FontData";
+ return "FontFile";
}
bool ResourceImporterImageFont::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -64,6 +64,9 @@ void ResourceImporterImageFont::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "columns"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "rows"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "font_size"), 14));
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), Array()));
+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
}
@@ -92,8 +95,9 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
int rows = p_options["rows"];
int base_size = p_options["font_size"];
Vector<String> ranges = p_options["character_ranges"];
+ Array fallbacks = p_options["fallbacks"];
- Ref<FontData> font;
+ Ref<FontFile> font;
font.instantiate();
font->set_antialiased(false);
font->set_generate_mipmaps(false);
@@ -103,6 +107,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
font->set_force_autohinter(false);
font->set_hinting(TextServer::HINTING_NONE);
font->set_oversampling(1.0f);
+ font->set_fallbacks(fallbacks);
Ref<Image> img;
img.instantiate();
@@ -145,10 +150,10 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
ERR_FAIL_COND_V_MSG(pos >= count, ERR_CANT_CREATE, "Too many characters in range.");
}
}
- font->set_ascent(0, base_size, 0.5 * chr_height);
- font->set_descent(0, base_size, 0.5 * chr_height);
+ font->set_cache_ascent(0, base_size, 0.5 * chr_height);
+ font->set_cache_descent(0, base_size, 0.5 * chr_height);
- int flg = ResourceSaver::SaverFlags::FLAG_BUNDLE_RESOURCES | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
+ int flg = 0;
if ((bool)p_options["compress"]) {
flg |= ResourceSaver::SaverFlags::FLAG_COMPRESS;
}
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 171ef5bf4c..860269bfcb 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -144,11 +144,11 @@ Variant EditorScenePostImportPlugin::get_option_value(const StringName &p_name)
ERR_FAIL_COND_V_MSG(current_options == nullptr && current_options_dict == nullptr, Variant(), "get_option_value called from a function where option values are not available.");
ERR_FAIL_COND_V_MSG(current_options && !current_options->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name));
ERR_FAIL_COND_V_MSG(current_options_dict && !current_options_dict->has(p_name), Variant(), "get_option_value called with unexisting option argument: " + String(p_name));
- if (current_options) {
- (*current_options)[p_name];
+ if (current_options && current_options->has(p_name)) {
+ return (*current_options)[p_name];
}
- if (current_options_dict) {
- (*current_options_dict)[p_name];
+ if (current_options_dict && current_options_dict->has(p_name)) {
+ return (*current_options_dict)[p_name];
}
return Variant();
}
@@ -232,6 +232,7 @@ void EditorScenePostImportPlugin::_bind_methods() {
BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MATERIAL);
BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION);
BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE);
+ BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE);
BIND_ENUM_CONSTANT(INTERNAL_IMPORT_CATEGORY_MAX);
}
@@ -766,6 +767,27 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
}
{
+ //make sure this is unique
+ node_settings = node_settings.duplicate(true);
+ //fill node settings for this node with default values
+ List<ImportOption> iopts;
+ if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE, &iopts);
+ } else if (Object::cast_to<AnimationPlayer>(p_node)) {
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts);
+ } else if (Object::cast_to<Skeleton3D>(p_node)) {
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE, &iopts);
+ } else {
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_NODE, &iopts);
+ }
+ for (const ImportOption &E : iopts) {
+ if (!node_settings.has(E.option.name)) {
+ node_settings[E.option.name] = E.default_value;
+ }
+ }
+ }
+
+ {
ObjectID node_id = p_node->get_instance_id();
for (int i = 0; i < post_importer_plugins.size(); i++) {
post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_NODE, p_root, p_node, Ref<Resource>(), node_settings);
@@ -785,6 +807,16 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
}
}
+ if (Object::cast_to<Skeleton3D>(p_node)) {
+ ObjectID node_id = p_node->get_instance_id();
+ for (int i = 0; i < post_importer_plugins.size(); i++) {
+ post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE, p_root, p_node, Ref<Resource>(), node_settings);
+ if (ObjectDB::get_instance(node_id) == nullptr) { //may have been erased, so do not continue
+ break;
+ }
+ }
+ }
+
if (Object::cast_to<ImporterMeshInstance3D>(p_node)) {
ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(p_node);
@@ -799,6 +831,16 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
if (!mat_id.is_empty() && p_material_data.has(mat_id)) {
Dictionary matdata = p_material_data[mat_id];
+ {
+ //fill node settings for this node with default values
+ List<ImportOption> iopts;
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MATERIAL, &iopts);
+ for (const ImportOption &E : iopts) {
+ if (!matdata.has(E.option.name)) {
+ matdata[E.option.name] = E.default_value;
+ }
+ }
+ }
for (int j = 0; j < post_importer_plugins.size(); j++) {
post_importer_plugins.write[j]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL, p_root, p_node, mat, matdata);
@@ -966,19 +1008,6 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
if (Object::cast_to<AnimationPlayer>(p_node)) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
- {
- //make sure this is unique
- node_settings = node_settings.duplicate(true);
- //fill node settings for this node with default values
- List<ImportOption> iopts;
- get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts);
- for (const ImportOption &E : iopts) {
- if (!node_settings.has(E.option.name)) {
- node_settings[E.option.name] = E.default_value;
- }
- }
- }
-
for (int i = 0; i < post_importer_plugins.size(); i++) {
post_importer_plugins.write[i]->internal_process(EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, p_root, p_node, Ref<Resource>(), node_settings);
}
@@ -1385,6 +1414,10 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "slice_" + itos(i + 1) + "/save_to_file/keep_custom_tracks"), false));
}
} break;
+ case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "import/skip_import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "retarget/bone_map", PROPERTY_HINT_RESOURCE_TYPE, "BoneMap", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), Variant()));
+ } break;
default: {
}
}
@@ -1499,6 +1532,12 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
}
}
} break;
+ case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: {
+ const bool use_retarget = p_options["retarget/bone_map"].get_validated_object() != nullptr;
+ if (p_option != "retarget/bone_map" && p_option.begins_with("retarget/")) {
+ return use_retarget;
+ }
+ } break;
default: {
}
}
@@ -1534,6 +1573,8 @@ bool ResourceImporterScene::get_internal_option_update_view_required(InternalImp
} break;
case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
} break;
+ case INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE: {
+ } break;
default: {
}
}
@@ -1622,6 +1663,16 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m
if (!mesh_id.is_empty() && p_mesh_data.has(mesh_id)) {
Dictionary mesh_settings = p_mesh_data[mesh_id];
+ {
+ //fill node settings for this node with default values
+ List<ImportOption> iopts;
+ get_internal_import_options(INTERNAL_IMPORT_CATEGORY_MESH, &iopts);
+ for (const ImportOption &E : iopts) {
+ if (!mesh_settings.has(E.option.name)) {
+ mesh_settings[E.option.name] = E.default_value;
+ }
+ }
+ }
if (mesh_settings.has("generate/shadow_meshes")) {
int shadow_meshes = mesh_settings["generate/shadow_meshes"];
@@ -1921,7 +1972,7 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
}
}
-Node *ResourceImporterScene::pre_import(const String &p_source_file) {
+Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashMap<StringName, Variant> &p_options) {
Ref<EditorSceneFormatImporter> importer;
String ext = p_source_file.get_extension().to_lower();
@@ -1946,8 +1997,13 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) {
ERR_FAIL_COND_V(!importer.is_valid(), nullptr);
+ int bake_fps = 30;
+ if (p_options.has(SNAME("animation/fps"))) {
+ bake_fps = p_options[SNAME("animation/fps")];
+ }
+
Error err = OK;
- Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, HashMap<StringName, Variant>(), 15, nullptr, &err);
+ Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_options, bake_fps, nullptr, &err);
if (!scene || err != OK) {
return nullptr;
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index 16cf3d651d..b77c1dccb4 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -106,6 +106,7 @@ public:
INTERNAL_IMPORT_CATEGORY_MATERIAL,
INTERNAL_IMPORT_CATEGORY_ANIMATION,
INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE,
+ INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE,
INTERNAL_IMPORT_CATEGORY_MAX
};
@@ -259,6 +260,7 @@ public:
INTERNAL_IMPORT_CATEGORY_MATERIAL = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MATERIAL,
INTERNAL_IMPORT_CATEGORY_ANIMATION = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION,
INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE,
+ INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE,
INTERNAL_IMPORT_CATEGORY_MAX = EditorScenePostImportPlugin::INTERNAL_IMPORT_CATEGORY_MAX
};
@@ -279,7 +281,7 @@ public:
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);
+ Node *pre_import(const String &p_source_file, const HashMap<StringName, Variant> &p_options);
virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
virtual bool has_advanced_options() const override;
diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp
index e5fe99890e..28653dac3e 100644
--- a/editor/import/resource_importer_texture_atlas.cpp
+++ b/editor/import/resource_importer_texture_atlas.cpp
@@ -88,13 +88,7 @@ Error ResourceImporterTextureAtlas::import(const String &p_source_file, const St
//use an xpm because it's size independent, the editor images are vector and size dependent
//it's a simple hack
Ref<Image> broken = memnew(Image((const char **)atlas_import_failed_xpm));
- Ref<ImageTexture> broken_texture;
- broken_texture.instantiate();
- broken_texture->create_from_image(broken);
-
- String target_file = p_save_path + ".tex";
-
- ResourceSaver::save(target_file, broken_texture);
+ ResourceSaver::save(p_save_path + ".tex", ImageTexture::create_from_image(broken));
return OK;
}
@@ -308,9 +302,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file
Ref<Texture2D> cache;
cache = ResourceCache::get_ref(p_group_file);
if (!cache.is_valid()) {
- Ref<ImageTexture> res_cache;
- res_cache.instantiate();
- res_cache->create_from_image(new_atlas);
+ Ref<ImageTexture> res_cache = ImageTexture::create_from_image(new_atlas);
res_cache->set_path(p_group_file);
cache = res_cache;
}
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 362940dc17..f0ba1eb7a1 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -162,7 +162,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
//Consider revision for engine version 3.0
compression_code = file->get_16();
if (compression_code != 1 && compression_code != 3) {
- ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead.");
+ ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM or IEEE float instead.");
}
format_channels = file->get_16();
@@ -180,6 +180,10 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid amount of bits in the sample (should be one of 8, 16, 24 or 32).");
}
+ if (compression_code == 3 && format_bits % 32) {
+ ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid amount of bits in the IEEE float sample (should be 32 or 64).");
+ }
+
/* Don't need anything else, continue */
format_found = true;
}
@@ -208,36 +212,46 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
data.resize(frames * format_channels);
- if (format_bits == 8) {
- for (int i = 0; i < frames * format_channels; i++) {
- // 8 bit samples are UNSIGNED
+ if (compression_code == 1) {
+ if (format_bits == 8) {
+ for (int i = 0; i < frames * format_channels; i++) {
+ // 8 bit samples are UNSIGNED
- data.write[i] = int8_t(file->get_8() - 128) / 128.f;
- }
- } else if (format_bits == 32 && compression_code == 3) {
- for (int i = 0; i < frames * format_channels; i++) {
- //32 bit IEEE Float
+ data.write[i] = int8_t(file->get_8() - 128) / 128.f;
+ }
+ } else if (format_bits == 16) {
+ for (int i = 0; i < frames * format_channels; i++) {
+ //16 bit SIGNED
- data.write[i] = file->get_float();
- }
- } else if (format_bits == 16) {
- for (int i = 0; i < frames * format_channels; i++) {
- //16 bit SIGNED
+ data.write[i] = int16_t(file->get_16()) / 32768.f;
+ }
+ } else {
+ for (int i = 0; i < frames * format_channels; i++) {
+ //16+ bits samples are SIGNED
+ // if sample is > 16 bits, just read extra bytes
+
+ uint32_t s = 0;
+ for (int b = 0; b < (format_bits >> 3); b++) {
+ s |= ((uint32_t)file->get_8()) << (b * 8);
+ }
+ s <<= (32 - format_bits);
- data.write[i] = int16_t(file->get_16()) / 32768.f;
+ data.write[i] = (int32_t(s) >> 16) / 32768.f;
+ }
}
- } else {
- for (int i = 0; i < frames * format_channels; i++) {
- //16+ bits samples are SIGNED
- // if sample is > 16 bits, just read extra bytes
-
- uint32_t s = 0;
- for (int b = 0; b < (format_bits >> 3); b++) {
- s |= ((uint32_t)file->get_8()) << (b * 8);
+ } else if (compression_code == 3) {
+ if (format_bits == 32) {
+ for (int i = 0; i < frames * format_channels; i++) {
+ //32 bit IEEE Float
+
+ data.write[i] = file->get_float();
}
- s <<= (32 - format_bits);
+ } else if (format_bits == 64) {
+ for (int i = 0; i < frames * format_channels; i++) {
+ //64 bit IEEE Float
- data.write[i] = (int32_t(s) >> 16) / 32768.f;
+ data.write[i] = file->get_double();
+ }
}
}
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 99d1658405..b682407307 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -135,6 +135,12 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
String import_id;
bool has_import_id = false;
+ bool created = false;
+ if (!material_set.has(p_material)) {
+ material_set.insert(p_material);
+ created = true;
+ }
+
if (p_material->has_meta("import_id")) {
import_id = p_material->get_meta("import_id");
has_import_id = true;
@@ -142,7 +148,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
import_id = p_material->get_name();
has_import_id = true;
} else {
- import_id = "@MATERIAL:" + itos(material_set.size());
+ import_id = "@MATERIAL:" + itos(material_set.size() - 1);
}
if (!material_map.has(import_id)) {
@@ -160,14 +166,12 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma
Ref<Texture2D> icon = get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons"));
TreeItem *item = p_tree->create_item(p_parent);
- item->set_text(0, p_material->get_name());
- item->set_icon(0, icon);
-
- bool created = false;
- if (!material_set.has(p_material)) {
- material_set.insert(p_material);
- created = true;
+ if (p_material->get_name().is_empty()) {
+ item->set_text(0, TTR("<Unnamed Material>"));
+ } else {
+ item->set_text(0, p_material->get_name());
}
+ item->set_icon(0, icon);
item->set_meta("type", "Material");
item->set_meta("import_id", import_id);
@@ -339,6 +343,8 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE;
} else if (Object::cast_to<AnimationPlayer>(p_node)) {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE;
+ } else if (Object::cast_to<Skeleton3D>(p_node)) {
+ category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE;
} else {
category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
}
@@ -536,12 +542,6 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati
scene_import_settings_data->settings = nullptr;
scene_import_settings_data->path = p_path;
- scene = ResourceImporterScene::get_scene_singleton()->pre_import(p_path); // Use the scene singleton here because we want to see the full thing.
- if (scene == nullptr) {
- EditorNode::get_singleton()->show_warning(TTR("Error opening scene"));
- return;
- }
-
// Visibility
data_mode->set_tab_hidden(1, p_for_animation);
data_mode->set_tab_hidden(2, p_for_animation);
@@ -587,6 +587,12 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati
}
}
+ scene = ResourceImporterScene::get_scene_singleton()->pre_import(p_path, defaults); // Use the scene singleton here because we want to see the full thing.
+ if (scene == nullptr) {
+ EditorNode::get_singleton()->show_warning(TTR("Error opening scene"));
+ return;
+ }
+
first_aabb = true;
_update_scene();
@@ -604,6 +610,9 @@ void SceneImportSettings::open_settings(const String &p_path, bool p_for_animati
_update_view_gizmos();
_update_camera();
+ // Start with the root item (Scene) selected.
+ scene_tree->get_root()->select(0);
+
if (p_for_animation) {
set_title(vformat(TTR("Advanced Import Settings for AnimationLibrary '%s'"), base_path.get_file()));
} else {
@@ -617,6 +626,13 @@ SceneImportSettings *SceneImportSettings::get_singleton() {
return singleton;
}
+Node *SceneImportSettings::get_selected_node() {
+ if (selected_id == "") {
+ return nullptr;
+ }
+ return node_map[selected_id].node;
+}
+
void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
selecting = true;
scene_import_settings_data->hide_options = false;
@@ -657,6 +673,8 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
scene_import_settings_data->hide_options = editing_animation;
} else if (Object::cast_to<AnimationPlayer>(nd.node)) {
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE;
+ } else if (Object::cast_to<Skeleton3D>(nd.node)) {
+ scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE;
} else {
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
scene_import_settings_data->hide_options = editing_animation;
diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h
index 81d13166ab..b5cf82f64b 100644
--- a/editor/import/scene_import_settings.h
+++ b/editor/import/scene_import_settings.h
@@ -201,6 +201,7 @@ public:
void update_view();
void open_settings(const String &p_path, bool p_for_animation = false);
static SceneImportSettings *get_singleton();
+ Node *get_selected_node();
SceneImportSettings();
~SceneImportSettings();
};
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index ad6d8e6379..affe46aaae 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -565,7 +565,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
String num = String::num(vertex.vertex);
- Size2 num_size = font->get_string_size(num, font_size);
+ Size2 num_size = font->get_string_size(num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
p_overlay->draw_string(font, point - num_size * 0.5, num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
}
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index 2e4dcab203..248ba021ce 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -215,7 +215,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
blend_space_draw->draw_rect(Rect2(Point2(), s), color, false);
}
- blend_space_draw->draw_line(Point2(1, s.height - 1), Point2(s.width - 1, s.height - 1), linecolor);
+ blend_space_draw->draw_line(Point2(1, s.height - 1), Point2(s.width - 1, s.height - 1), linecolor, Math::round(EDSCALE));
if (blend_space->get_min_space() < 0) {
float point = 0.0;
@@ -224,9 +224,9 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
float x = point;
- blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor);
+ blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor, Math::round(EDSCALE));
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height(font_size) + font->get_ascent(font_size)), "0", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, linecolor);
- blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft);
+ blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft, Math::round(EDSCALE));
}
if (snap->is_pressed()) {
@@ -240,7 +240,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
int idx = int(v / blend_space->get_snap());
if (i > 0 && prev_idx != idx) {
- blend_space_draw->draw_line(Point2(i, 0), Point2(i, s.height), linecolor_soft);
+ blend_space_draw->draw_line(Point2(i, 0), Point2(i, s.height), linecolor_soft, Math::round(EDSCALE));
}
prev_idx = idx;
@@ -297,10 +297,10 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
float mind = 5 * EDSCALE;
float maxd = 15 * EDSCALE;
- blend_space_draw->draw_line(gui_point + Vector2(mind, 0), gui_point + Vector2(maxd, 0), color, 2);
- blend_space_draw->draw_line(gui_point + Vector2(-mind, 0), gui_point + Vector2(-maxd, 0), color, 2);
- blend_space_draw->draw_line(gui_point + Vector2(0, mind), gui_point + Vector2(0, maxd), color, 2);
- blend_space_draw->draw_line(gui_point + Vector2(0, -mind), gui_point + Vector2(0, -maxd), color, 2);
+ blend_space_draw->draw_line(gui_point + Vector2(mind, 0), gui_point + Vector2(maxd, 0), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(gui_point + Vector2(-mind, 0), gui_point + Vector2(-maxd, 0), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(gui_point + Vector2(0, mind), gui_point + Vector2(0, maxd), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(gui_point + Vector2(0, -mind), gui_point + Vector2(0, -maxd), color, Math::round(2 * EDSCALE));
}
}
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 86addde87b..dfde63ecb6 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -407,22 +407,22 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
Color color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
blend_space_draw->draw_rect(Rect2(Point2(), s), color, false);
}
- blend_space_draw->draw_line(Point2(1, 0), Point2(1, s.height - 1), linecolor);
- blend_space_draw->draw_line(Point2(1, s.height - 1), Point2(s.width - 1, s.height - 1), linecolor);
+ blend_space_draw->draw_line(Point2(1, 0), Point2(1, s.height - 1), linecolor, Math::round(EDSCALE));
+ blend_space_draw->draw_line(Point2(1, s.height - 1), Point2(s.width - 1, s.height - 1), linecolor, Math::round(EDSCALE));
- blend_space_draw->draw_line(Point2(0, 0), Point2(5 * EDSCALE, 0), linecolor);
+ blend_space_draw->draw_line(Point2(0, 0), Point2(5 * EDSCALE, 0), linecolor, Math::round(EDSCALE));
if (blend_space->get_min_space().y < 0) {
int y = (blend_space->get_max_space().y / (blend_space->get_max_space().y - blend_space->get_min_space().y)) * s.height;
- blend_space_draw->draw_line(Point2(0, y), Point2(5 * EDSCALE, y), linecolor);
+ blend_space_draw->draw_line(Point2(0, y), Point2(5 * EDSCALE, y), linecolor, Math::round(EDSCALE));
blend_space_draw->draw_string(font, Point2(2 * EDSCALE, y - font->get_height(font_size) + font->get_ascent(font_size)), "0", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, linecolor);
- blend_space_draw->draw_line(Point2(5 * EDSCALE, y), Point2(s.width, y), linecolor_soft);
+ blend_space_draw->draw_line(Point2(5 * EDSCALE, y), Point2(s.width, y), linecolor_soft, Math::round(EDSCALE));
}
if (blend_space->get_min_space().x < 0) {
int x = (-blend_space->get_min_space().x / (blend_space->get_max_space().x - blend_space->get_min_space().x)) * s.width;
- blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor);
+ blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor, Math::round(EDSCALE));
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height(font_size) + font->get_ascent(font_size)), "0", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, linecolor);
- blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft);
+ blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft, Math::round(EDSCALE));
}
if (snap->is_pressed()) {
@@ -435,7 +435,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
int idx = int(v / blend_space->get_snap().x);
if (i > 0 && prev_idx != idx) {
- blend_space_draw->draw_line(Point2(i, 0), Point2(i, s.height), linecolor_soft);
+ blend_space_draw->draw_line(Point2(i, 0), Point2(i, s.height), linecolor_soft, Math::round(EDSCALE));
}
prev_idx = idx;
@@ -449,7 +449,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
int idx = int(v / blend_space->get_snap().y);
if (i > 0 && prev_idx != idx) {
- blend_space_draw->draw_line(Point2(0, i), Point2(s.width, i), linecolor_soft);
+ blend_space_draw->draw_line(Point2(0, i), Point2(s.width, i), linecolor_soft, Math::round(EDSCALE));
}
prev_idx = idx;
@@ -478,7 +478,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
}
for (int j = 0; j < 3; j++) {
- blend_space_draw->draw_line(points[j], points[(j + 1) % 3], linecolor, 1);
+ blend_space_draw->draw_line(points[j], points[(j + 1) % 3], linecolor, Math::round(EDSCALE), true);
}
Color color;
@@ -533,9 +533,9 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
}
for (int i = 0; i < points.size() - 1; i++) {
- blend_space_draw->draw_line(points[i], points[i + 1], linecolor, 2);
+ blend_space_draw->draw_line(points[i], points[i + 1], linecolor, Math::round(2 * EDSCALE), true);
}
- blend_space_draw->draw_line(points[points.size() - 1], blend_space_draw->get_local_mouse_position(), linecolor, 2);
+ blend_space_draw->draw_line(points[points.size() - 1], blend_space_draw->get_local_mouse_position(), linecolor, Math::round(2 * EDSCALE), true);
}
///draw cursor position
@@ -564,15 +564,15 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
Color lcol = color;
lcol.a *= 0.4;
- blend_space_draw->draw_line(point, closest, lcol, 2);
+ blend_space_draw->draw_line(point, closest, lcol, Math::round(2 * EDSCALE), true);
}
float mind = 5 * EDSCALE;
float maxd = 15 * EDSCALE;
- blend_space_draw->draw_line(point + Vector2(mind, 0), point + Vector2(maxd, 0), color, 2);
- blend_space_draw->draw_line(point + Vector2(-mind, 0), point + Vector2(-maxd, 0), color, 2);
- blend_space_draw->draw_line(point + Vector2(0, mind), point + Vector2(0, maxd), color, 2);
- blend_space_draw->draw_line(point + Vector2(0, -mind), point + Vector2(0, -maxd), color, 2);
+ blend_space_draw->draw_line(point + Vector2(mind, 0), point + Vector2(maxd, 0), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(point + Vector2(-mind, 0), point + Vector2(-maxd, 0), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(point + Vector2(0, mind), point + Vector2(0, maxd), color, Math::round(2 * EDSCALE));
+ blend_space_draw->draw_line(point + Vector2(0, -mind), point + Vector2(0, -maxd), color, Math::round(2 * EDSCALE));
}
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index e5ca5d66e8..8d1755d260 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -135,7 +135,7 @@ void AnimationPlayerEditor::_notification(int p_what) {
autoplay_reset_img->blit_rect(autoplay_img, Rect2(Point2(), icon_size), Point2());
autoplay_reset_img->blit_rect(reset_img, Rect2(Point2(), icon_size), Point2(icon_size.x, 0));
autoplay_reset_icon.instantiate();
- autoplay_reset_icon->create_from_image(autoplay_reset_img);
+ autoplay_reset_icon->set_image(autoplay_reset_img);
}
stop->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")));
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 00cc5a6ca0..05d7a5f973 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -1224,7 +1224,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<StyleBox> sb = selected_nodes.has(E) ? style_selected : style;
Size2 s = sb->get_minimum_size();
- int strsize = font->get_string_size(name, font_size).width;
+ int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
s.width += strsize;
s.height += MAX(font->get_height(font_size), play->get_height());
s.width += sep + play->get_width();
@@ -1379,7 +1379,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<AnimationNode> anode = state_machine->get_node(name);
bool needs_editor = AnimationTreeEditor::get_singleton()->can_edit(anode);
Ref<StyleBox> sb = selected_nodes.has(name) ? style_selected : style;
- int strsize = font->get_string_size(name, font_size).width;
+ int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
NodeRect &nr = node_rects.write[i];
Vector2 offset = nr.node.position;
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index e9435faae1..12ab9e3b61 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -165,14 +165,9 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
// Overlay and thumbnail need the same format for `blend_rect` to work.
thumbnail->convert(Image::FORMAT_RGBA8);
-
thumbnail->blend_rect(overlay, overlay->get_used_rect(), overlay_pos);
+ preview_images[i].button->set_icon(ImageTexture::create_from_image(thumbnail));
- Ref<ImageTexture> tex;
- tex.instantiate();
- tex->create_from_image(thumbnail);
-
- preview_images[i].button->set_icon(tex);
// Make it clearer that clicking it will open an external link
preview_images[i].button->set_default_cursor_shape(Control::CURSOR_POINTING_HAND);
} else {
@@ -291,12 +286,15 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
hbox->add_child(previews_vbox);
previews_vbox->add_theme_constant_override("separation", 15 * EDSCALE);
previews_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ previews_vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
preview = memnew(TextureRect);
previews_vbox->add_child(preview);
preview->set_ignore_texture_size(true);
preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
preview->set_custom_minimum_size(Size2(640 * EDSCALE, 345 * EDSCALE));
+ preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ preview->set_h_size_flags(Control::SIZE_EXPAND_FILL);
previews_bg = memnew(PanelContainer);
previews_vbox->add_child(previews_bg);
@@ -621,6 +619,10 @@ void EditorAssetLibrary::_notification(int p_what) {
} break;
+ case NOTIFICATION_RESIZED: {
+ _update_asset_items_columns();
+ } break;
+
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
_update_repository_options();
setup_http_request(request);
@@ -783,9 +785,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
} break;
}
- Ref<ImageTexture> tex;
- tex.instantiate();
- tex->create_from_image(image);
+ Ref<ImageTexture> tex = ImageTexture::create_from_image(image);
obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, tex);
image_set = true;
@@ -1210,7 +1210,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
library_vb->add_child(asset_top_page);
asset_items = memnew(GridContainer);
- asset_items->set_columns(2);
+ _update_asset_items_columns();
asset_items->add_theme_constant_override("h_separation", 10 * EDSCALE);
asset_items->add_theme_constant_override("v_separation", 10 * EDSCALE);
@@ -1376,12 +1376,17 @@ void EditorAssetLibrary::_install_external_asset(String p_zip_path, String p_tit
emit_signal(SNAME("install_asset"), p_zip_path, p_title);
}
-void EditorAssetLibrary::disable_community_support() {
- support->get_popup()->set_item_checked(SUPPORT_COMMUNITY, false);
+void EditorAssetLibrary::_update_asset_items_columns() {
+ int new_columns = get_size().x / (450.0 * EDSCALE);
+ new_columns = MAX(1, new_columns);
+
+ if (new_columns != asset_items->get_columns()) {
+ asset_items->set_columns(new_columns);
+ }
}
-void EditorAssetLibrary::set_columns(const int p_columns) {
- asset_items->set_columns(p_columns);
+void EditorAssetLibrary::disable_community_support() {
+ support->get_popup()->set_item_checked(SUPPORT_COMMUNITY, false);
}
void EditorAssetLibrary::_bind_methods() {
@@ -1539,7 +1544,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
library_vb->add_child(asset_top_page);
asset_items = memnew(GridContainer);
- asset_items->set_columns(2);
+ _update_asset_items_columns();
asset_items->add_theme_constant_override("h_separation", 10 * EDSCALE);
asset_items->add_theme_constant_override("v_separation", 10 * EDSCALE);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 2b43719cdd..e02662b8db 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -301,6 +301,8 @@ class EditorAssetLibrary : public PanelContainer {
void _install_external_asset(String p_zip_path, String p_title);
+ void _update_asset_items_columns();
+
friend class EditorAssetLibraryItemDescription;
friend class EditorAssetLibraryItem;
@@ -311,7 +313,6 @@ protected:
public:
void disable_community_support();
- void set_columns(int p_columns);
EditorAssetLibrary(bool p_templates_only = false);
};
diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp
index 9003c4480b..657c5a36b6 100644
--- a/editor/plugins/bit_map_editor_plugin.cpp
+++ b/editor/plugins/bit_map_editor_plugin.cpp
@@ -33,11 +33,7 @@
#include "editor/editor_scale.h"
void BitMapEditor::setup(const Ref<BitMap> &p_bitmap) {
- Ref<ImageTexture> texture;
- texture.instantiate();
- texture->create_from_image(p_bitmap->convert_to_image());
- texture_rect->set_texture(texture);
-
+ texture_rect->set_texture(ImageTexture::create_from_image(p_bitmap->convert_to_image()));
size_label->set_text(vformat(String::utf8("%s×%s"), p_bitmap->get_size().width, p_bitmap->get_size().height));
}
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
new file mode 100644
index 0000000000..fffadae3eb
--- /dev/null
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -0,0 +1,439 @@
+/*************************************************************************/
+/* bone_map_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "bone_map_editor_plugin.h"
+
+#include "editor/editor_scale.h"
+#include "editor/import/post_import_plugin_skeleton_renamer.h"
+#include "editor/import/scene_import_settings.h"
+
+void BoneMapperButton::fetch_textures() {
+ if (selected) {
+ set_normal_texture(get_theme_icon(SNAME("BoneMapperHandleSelected"), SNAME("EditorIcons")));
+ } else {
+ set_normal_texture(get_theme_icon(SNAME("BoneMapperHandle"), SNAME("EditorIcons")));
+ }
+ set_offset(SIDE_LEFT, 0);
+ set_offset(SIDE_RIGHT, 0);
+ set_offset(SIDE_TOP, 0);
+ set_offset(SIDE_BOTTOM, 0);
+
+ circle = memnew(TextureRect);
+ circle->set_texture(get_theme_icon(SNAME("BoneMapperHandleCircle"), SNAME("EditorIcons")));
+ add_child(circle);
+ set_state(BONE_MAP_STATE_UNSET);
+}
+
+StringName BoneMapperButton::get_profile_bone_name() const {
+ return profile_bone_name;
+}
+
+void BoneMapperButton::set_state(BoneMapState p_state) {
+ switch (p_state) {
+ case BONE_MAP_STATE_UNSET: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/unset"));
+ } break;
+ case BONE_MAP_STATE_SET: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/set"));
+ } break;
+ case BONE_MAP_STATE_ERROR: {
+ circle->set_modulate(EditorSettings::get_singleton()->get("editors/bone_mapper/handle_colors/error"));
+ } break;
+ default: {
+ } break;
+ }
+}
+
+void BoneMapperButton::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ fetch_textures();
+ } break;
+ }
+}
+
+BoneMapperButton::BoneMapperButton(const StringName p_profile_bone_name, bool p_selected) {
+ profile_bone_name = p_profile_bone_name;
+ selected = p_selected;
+}
+
+BoneMapperButton::~BoneMapperButton() {
+}
+
+void BoneMapperItem::create_editor() {
+ skeleton_bone_selector = memnew(EditorPropertyTextEnum);
+ skeleton_bone_selector->setup(skeleton_bone_names);
+ skeleton_bone_selector->set_label(profile_bone_name);
+ skeleton_bone_selector->set_selectable(false);
+ skeleton_bone_selector->set_object_and_property(bone_map.ptr(), "bone_map/" + String(profile_bone_name));
+ skeleton_bone_selector->update_property();
+ skeleton_bone_selector->connect("property_changed", callable_mp(this, &BoneMapperItem::_value_changed));
+ add_child(skeleton_bone_selector);
+}
+
+void BoneMapperItem::_update_property() {
+ if (skeleton_bone_selector->get_edited_object() && skeleton_bone_selector->get_edited_property()) {
+ skeleton_bone_selector->update_property();
+ }
+}
+
+void BoneMapperItem::_value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ bone_map->set(p_property, p_value);
+}
+
+void BoneMapperItem::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ create_editor();
+ bone_map->connect("bone_map_updated", callable_mp(this, &BoneMapperItem::_update_property));
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (!bone_map.is_null() && bone_map->is_connected("bone_map_updated", callable_mp(this, &BoneMapperItem::_update_property))) {
+ bone_map->disconnect("bone_map_updated", callable_mp(this, &BoneMapperItem::_update_property));
+ }
+ } break;
+ }
+}
+
+void BoneMapperItem::_bind_methods() {
+}
+
+BoneMapperItem::BoneMapperItem(Ref<BoneMap> &p_bone_map, PackedStringArray p_skeleton_bone_names, const StringName &p_profile_bone_name) {
+ bone_map = p_bone_map;
+ skeleton_bone_names = p_skeleton_bone_names;
+ profile_bone_name = p_profile_bone_name;
+}
+
+BoneMapperItem::~BoneMapperItem() {
+}
+
+void BoneMapper::create_editor() {
+ profile_group_selector = memnew(EditorPropertyEnum);
+ profile_group_selector->set_label("Group");
+ profile_group_selector->set_selectable(false);
+ profile_group_selector->set_object_and_property(this, "current_group_idx");
+ profile_group_selector->update_property();
+ profile_group_selector->connect("property_changed", callable_mp(this, &BoneMapper::_value_changed));
+ add_child(profile_group_selector);
+
+ bone_mapper_field = memnew(AspectRatioContainer);
+ bone_mapper_field->set_stretch_mode(AspectRatioContainer::STRETCH_FIT);
+ bone_mapper_field->set_custom_minimum_size(Vector2(0, 256.0) * EDSCALE);
+ bone_mapper_field->set_h_size_flags(Control::SIZE_FILL);
+ add_child(bone_mapper_field);
+
+ profile_bg = memnew(ColorRect);
+ profile_bg->set_color(Color(0, 0, 0, 1));
+ profile_bg->set_h_size_flags(Control::SIZE_FILL);
+ profile_bg->set_v_size_flags(Control::SIZE_FILL);
+ bone_mapper_field->add_child(profile_bg);
+
+ profile_texture = memnew(TextureRect);
+ profile_texture->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ profile_texture->set_ignore_texture_size(true);
+ profile_texture->set_h_size_flags(Control::SIZE_FILL);
+ profile_texture->set_v_size_flags(Control::SIZE_FILL);
+ bone_mapper_field->add_child(profile_texture);
+
+ mapper_item_vbox = memnew(VBoxContainer);
+ add_child(mapper_item_vbox);
+
+ separator = memnew(HSeparator);
+ add_child(separator);
+
+ recreate_items();
+}
+
+void BoneMapper::update_group_idx() {
+ if (!bone_map->get_profile().is_valid()) {
+ return;
+ }
+
+ PackedStringArray group_names;
+ int len = bone_map->get_profile()->get_group_size();
+ for (int i = 0; i < len; i++) {
+ group_names.push_back(bone_map->get_profile()->get_group_name(i));
+ }
+ if (current_group_idx >= len) {
+ current_group_idx = 0;
+ }
+ if (len > 0) {
+ profile_group_selector->setup(group_names);
+ profile_group_selector->update_property();
+ profile_group_selector->set_read_only(false);
+ }
+}
+
+void BoneMapper::set_current_group_idx(int p_group_idx) {
+ current_group_idx = p_group_idx;
+ recreate_editor();
+}
+
+int BoneMapper::get_current_group_idx() const {
+ return current_group_idx;
+}
+
+void BoneMapper::set_current_bone_idx(int p_bone_idx) {
+ current_bone_idx = p_bone_idx;
+ recreate_editor();
+}
+
+int BoneMapper::get_current_bone_idx() const {
+ return current_bone_idx;
+}
+
+void BoneMapper::recreate_editor() {
+ // Clear buttons.
+ int len = bone_mapper_buttons.size();
+ for (int i = 0; i < len; i++) {
+ profile_texture->remove_child(bone_mapper_buttons[i]);
+ memdelete(bone_mapper_buttons[i]);
+ }
+ bone_mapper_buttons.clear();
+
+ // Organize mapper items.
+ len = bone_mapper_items.size();
+ for (int i = 0; i < len; i++) {
+ bone_mapper_items[i]->set_visible(current_bone_idx == i);
+ }
+
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (profile.is_valid()) {
+ SkeletonProfileHumanoid *hmn = Object::cast_to<SkeletonProfileHumanoid>(profile.ptr());
+ if (hmn) {
+ StringName hmn_group_name = profile->get_group_name(current_group_idx);
+ if (hmn_group_name == "Body") {
+ profile_texture->set_texture(get_theme_icon(SNAME("BoneMapHumanBody"), SNAME("EditorIcons")));
+ } else if (hmn_group_name == "Face") {
+ profile_texture->set_texture(get_theme_icon(SNAME("BoneMapHumanFace"), SNAME("EditorIcons")));
+ } else if (hmn_group_name == "LeftHand") {
+ profile_texture->set_texture(get_theme_icon(SNAME("BoneMapHumanLeftHand"), SNAME("EditorIcons")));
+ } else if (hmn_group_name == "RightHand") {
+ profile_texture->set_texture(get_theme_icon(SNAME("BoneMapHumanRightHand"), SNAME("EditorIcons")));
+ }
+ } else {
+ profile_texture->set_texture(profile->get_texture(current_group_idx));
+ }
+ } else {
+ profile_texture->set_texture(Ref<Texture2D>());
+ }
+
+ if (!profile.is_valid()) {
+ return;
+ }
+
+ for (int i = 0; i < len; i++) {
+ if (profile->get_group(i) == profile->get_group_name(current_group_idx)) {
+ BoneMapperButton *mb = memnew(BoneMapperButton(profile->get_bone_name(i), current_bone_idx == i));
+ mb->connect("pressed", callable_mp(this, &BoneMapper::set_current_bone_idx), varray(i), CONNECT_DEFERRED);
+ mb->set_h_grow_direction(GROW_DIRECTION_BOTH);
+ mb->set_v_grow_direction(GROW_DIRECTION_BOTH);
+ Vector2 vc = profile->get_handle_offset(i);
+ bone_mapper_buttons.push_back(mb);
+ profile_texture->add_child(mb);
+ mb->set_anchor(SIDE_LEFT, vc.x);
+ mb->set_anchor(SIDE_RIGHT, vc.x);
+ mb->set_anchor(SIDE_TOP, vc.y);
+ mb->set_anchor(SIDE_BOTTOM, vc.y);
+ }
+ }
+
+ _update_state();
+}
+
+void BoneMapper::clear_items() {
+ // Clear items.
+ int len = bone_mapper_items.size();
+ for (int i = 0; i < len; i++) {
+ mapper_item_vbox->remove_child(bone_mapper_items[i]);
+ memdelete(bone_mapper_items[i]);
+ }
+ bone_mapper_items.clear();
+}
+
+void BoneMapper::recreate_items() {
+ clear_items();
+ // Create items by profile.
+ Ref<SkeletonProfile> profile = bone_map->get_profile();
+ if (profile.is_valid()) {
+ PackedStringArray skeleton_bone_names;
+ skeleton_bone_names.push_back(String());
+
+ int len = skeleton->get_bone_count();
+ for (int i = 0; i < len; i++) {
+ skeleton_bone_names.push_back(skeleton->get_bone_name(i));
+ }
+
+ len = profile->get_bone_size();
+ for (int i = 0; i < len; i++) {
+ StringName bn = profile->get_bone_name(i);
+ bone_mapper_items.append(memnew(BoneMapperItem(bone_map, skeleton_bone_names, bn)));
+ mapper_item_vbox->add_child(bone_mapper_items[i]);
+ }
+ }
+
+ update_group_idx();
+ recreate_editor();
+}
+
+void BoneMapper::_update_state() {
+ int len = bone_mapper_buttons.size();
+ for (int i = 0; i < len; i++) {
+ StringName sbn = bone_map->get_skeleton_bone_name(bone_mapper_buttons[i]->get_profile_bone_name());
+ if (skeleton->find_bone(sbn) >= 0) {
+ if (bone_map->get_skeleton_bone_name_count(sbn) == 1) {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_SET);
+ } else {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_ERROR);
+ }
+ } else {
+ bone_mapper_buttons[i]->set_state(BoneMapperButton::BONE_MAP_STATE_UNSET);
+ }
+ }
+}
+
+void BoneMapper::_value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ set(p_property, p_value);
+ recreate_editor();
+}
+
+void BoneMapper::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_current_group_idx", "current_group_idx"), &BoneMapper::set_current_group_idx);
+ ClassDB::bind_method(D_METHOD("get_current_group_idx"), &BoneMapper::get_current_group_idx);
+ ClassDB::bind_method(D_METHOD("set_current_bone_idx", "current_bone_idx"), &BoneMapper::set_current_bone_idx);
+ ClassDB::bind_method(D_METHOD("get_current_bone_idx"), &BoneMapper::get_current_bone_idx);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "current_group_idx"), "set_current_group_idx", "get_current_group_idx");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "current_bone_idx"), "set_current_bone_idx", "get_current_bone_idx");
+}
+
+void BoneMapper::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ create_editor();
+ bone_map->connect("bone_map_updated", callable_mp(this, &BoneMapper::_update_state));
+ bone_map->connect("profile_updated", callable_mp(this, &BoneMapper::recreate_items));
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ clear_items();
+ if (!bone_map.is_null()) {
+ if (bone_map->is_connected("bone_map_updated", callable_mp(this, &BoneMapper::_update_state))) {
+ bone_map->disconnect("bone_map_updated", callable_mp(this, &BoneMapper::_update_state));
+ }
+ if (bone_map->is_connected("profile_updated", callable_mp(this, &BoneMapper::recreate_items))) {
+ bone_map->disconnect("profile_updated", callable_mp(this, &BoneMapper::recreate_items));
+ }
+ }
+ }
+ }
+}
+
+BoneMapper::BoneMapper(Skeleton3D *p_skeleton, Ref<BoneMap> &p_bone_map) {
+ skeleton = p_skeleton;
+ bone_map = p_bone_map;
+}
+
+BoneMapper::~BoneMapper() {
+}
+
+void BoneMapEditor::create_editors() {
+ if (!skeleton) {
+ return;
+ }
+ bone_mapper = memnew(BoneMapper(skeleton, bone_map));
+ add_child(bone_mapper);
+}
+
+void BoneMapEditor::fetch_objects() {
+ // Hackey... but it may be the easist way to get a selected object from "ImporterScene".
+ SceneImportSettings *si = SceneImportSettings::get_singleton();
+ if (!si) {
+ return;
+ }
+ Node *selected = si->get_selected_node();
+ if (selected) {
+ Skeleton3D *sk = Object::cast_to<Skeleton3D>(selected);
+ if (!sk) {
+ return;
+ }
+ skeleton = sk;
+ } else {
+ // Editor should not exist.
+ skeleton = nullptr;
+ }
+}
+
+void BoneMapEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ fetch_objects();
+ create_editors();
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ remove_child(bone_mapper);
+ bone_mapper->queue_delete();
+ }
+ }
+}
+
+BoneMapEditor::BoneMapEditor(Ref<BoneMap> &p_bone_map) {
+ bone_map = p_bone_map;
+}
+
+BoneMapEditor::~BoneMapEditor() {
+}
+
+bool EditorInspectorPluginBoneMap::can_handle(Object *p_object) {
+ return Object::cast_to<BoneMap>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginBoneMap::parse_begin(Object *p_object) {
+ BoneMap *bm = Object::cast_to<BoneMap>(p_object);
+ if (!bm) {
+ return;
+ }
+ Ref<BoneMap> r(bm);
+ editor = memnew(BoneMapEditor(r));
+ add_custom_control(editor);
+}
+
+BoneMapEditorPlugin::BoneMapEditorPlugin() {
+ // Register properties in editor settings.
+ EDITOR_DEF("editors/bone_mapper/handle_colors/set", Color(0.1, 0.6, 0.25));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/error", Color(0.8, 0.2, 0.2));
+ EDITOR_DEF("editors/bone_mapper/handle_colors/unset", Color(0.3, 0.3, 0.3));
+
+ Ref<EditorInspectorPluginBoneMap> inspector_plugin;
+ inspector_plugin.instantiate();
+ add_inspector_plugin(inspector_plugin);
+
+ Ref<PostImportPluginSkeletonRenamer> post_import_plugin_renamer;
+ post_import_plugin_renamer.instantiate();
+ add_scene_post_import_plugin(post_import_plugin_renamer);
+}
diff --git a/editor/plugins/bone_map_editor_plugin.h b/editor/plugins/bone_map_editor_plugin.h
new file mode 100644
index 0000000000..0ec9f74373
--- /dev/null
+++ b/editor/plugins/bone_map_editor_plugin.h
@@ -0,0 +1,176 @@
+/*************************************************************************/
+/* bone_map_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef BONE_MAP_EDITOR_H
+#define BONE_MAP_EDITOR_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_properties.h"
+#include "scene/3d/skeleton_3d.h"
+#include "scene/gui/color_rect.h"
+#include "scene/gui/dialogs.h"
+#include "scene/resources/bone_map.h"
+#include "scene/resources/texture.h"
+
+class BoneMapperButton : public TextureButton {
+ GDCLASS(BoneMapperButton, TextureButton);
+
+public:
+ enum BoneMapState {
+ BONE_MAP_STATE_UNSET,
+ BONE_MAP_STATE_SET,
+ BONE_MAP_STATE_ERROR
+ };
+
+private:
+ StringName profile_bone_name;
+ bool selected = false;
+
+ TextureRect *circle;
+
+ void fetch_textures();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ StringName get_profile_bone_name() const;
+ void set_state(BoneMapState p_state);
+
+ BoneMapperButton(const StringName p_profile_bone_name, bool p_selected);
+ ~BoneMapperButton();
+};
+
+class BoneMapperItem : public VBoxContainer {
+ GDCLASS(BoneMapperItem, VBoxContainer);
+
+ int button_id = -1;
+ StringName profile_bone_name;
+
+ PackedStringArray skeleton_bone_names;
+ Ref<BoneMap> bone_map;
+
+ EditorPropertyTextEnum *skeleton_bone_selector;
+
+ void _update_property();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ virtual void _value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
+ virtual void create_editor();
+
+public:
+ void assign_button_id(int p_button_id);
+
+ BoneMapperItem(Ref<BoneMap> &p_bone_map, PackedStringArray p_skeleton_bone_names, const StringName &p_profile_bone_name = StringName());
+ ~BoneMapperItem();
+};
+
+class BoneMapper : public VBoxContainer {
+ GDCLASS(BoneMapper, VBoxContainer);
+
+ Skeleton3D *skeleton;
+ Ref<BoneMap> bone_map;
+
+ Vector<BoneMapperItem *> bone_mapper_items;
+
+ VBoxContainer *mapper_item_vbox;
+ HSeparator *separator;
+
+ int current_group_idx = 0;
+ int current_bone_idx = -1;
+
+ AspectRatioContainer *bone_mapper_field;
+ EditorPropertyEnum *profile_group_selector;
+ ColorRect *profile_bg;
+ TextureRect *profile_texture;
+ Vector<BoneMapperButton *> bone_mapper_buttons;
+
+ void create_editor();
+ void recreate_editor();
+ void clear_items();
+ void recreate_items();
+ void update_group_idx();
+ void _update_state();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ virtual void _value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
+
+public:
+ void set_current_group_idx(int p_group_idx);
+ int get_current_group_idx() const;
+ void set_current_bone_idx(int p_bone_idx);
+ int get_current_bone_idx() const;
+
+ BoneMapper(Skeleton3D *p_skeleton, Ref<BoneMap> &p_bone_map);
+ ~BoneMapper();
+};
+
+class BoneMapEditor : public VBoxContainer {
+ GDCLASS(BoneMapEditor, VBoxContainer);
+
+ Skeleton3D *skeleton;
+ Ref<BoneMap> bone_map;
+ BoneMapper *bone_mapper;
+
+ void fetch_objects();
+ void clear_editors();
+ void create_editors();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ BoneMapEditor(Ref<BoneMap> &p_bone_map);
+ ~BoneMapEditor();
+};
+
+class EditorInspectorPluginBoneMap : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginBoneMap, EditorInspectorPlugin);
+ BoneMapEditor *editor;
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+};
+
+class BoneMapEditorPlugin : public EditorPlugin {
+ GDCLASS(BoneMapEditorPlugin, EditorPlugin);
+
+public:
+ virtual String get_name() const override { return "BoneMap"; }
+ BoneMapEditorPlugin();
+};
+
+#endif // BONE_MAP_EDITOR_H
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index dea4aaded7..7e525a4698 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -813,9 +813,17 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
}
void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
+ original_transform = Transform2D();
+ bool transform_stored = false;
+
for (CanvasItem *canvas_item : p_canvas_items) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (se) {
+ if (!transform_stored) {
+ original_transform = canvas_item->get_global_transform();
+ transform_stored = true;
+ }
+
se->undo_state = canvas_item->_edit_get_state();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
if (canvas_item->_edit_use_rect()) {
@@ -2669,7 +2677,7 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string
color.a = 0.8;
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
- Size2 text_size = font->get_string_size(p_string, font_size);
+ Size2 text_size = font->get_string_size(p_string, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
switch (p_side) {
case SIDE_LEFT:
p_position += Vector2(-text_size.x - 5, text_size.y / 2);
@@ -2741,16 +2749,18 @@ void CanvasItemEditor::_draw_guides() {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)));
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
- Size2 text_size = font->get_string_size(str, font_size);
- viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color);
+ Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ viewport->draw_string_outline(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
}
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)));
Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
- Size2 text_size = font->get_string_size(str, font_size);
- viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color);
+ Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ viewport->draw_string_outline(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
}
}
@@ -2962,13 +2972,15 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
if (begin.is_equal_approx(end)) {
- viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons"));
viewport->draw_texture(get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons")), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
return;
}
- viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
@@ -2986,16 +2998,19 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 v_angle_text_pos = Point2();
v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
- viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 h_angle_text_pos = Point2();
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
@@ -3012,7 +3027,8 @@ void CanvasItemEditor::_draw_ruler_tool() {
h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
}
}
- viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
// Angle arcs
int arc_point_count = 8;
@@ -3047,17 +3063,21 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2);
if (draw_secondary_lines) {
- viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
} else {
- viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color);
+ viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
+ viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
}
}
} else {
@@ -3603,7 +3623,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, font_size);
+ Size2 node_name_size = font->get_string_size(node_name, HORIZONTAL_ALIGNMENT_LEFT, -1, 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);
@@ -3624,6 +3644,67 @@ void CanvasItemEditor::_draw_hover() {
}
}
+void CanvasItemEditor::_draw_transform_message() {
+ if (drag_selection.is_empty() || !drag_selection.front()->get()) {
+ return;
+ }
+ String transform_message;
+ Transform2D current_transform = drag_selection.front()->get()->get_global_transform();
+
+ double snap = EDITOR_GET("interface/inspector/default_float_step");
+ int snap_step_decimals = Math::range_step_decimals(snap);
+#define FORMAT(value) (TS->format_number(String::num(value, snap_step_decimals)))
+
+ switch (drag_type) {
+ case DRAG_MOVE:
+ case DRAG_MOVE_X:
+ case DRAG_MOVE_Y: {
+ Vector2 delta = current_transform.get_origin() - original_transform.get_origin();
+ if (drag_type == DRAG_MOVE) {
+ transform_message = TTR("Moving:") + " (" + FORMAT(delta.x) + ", " + FORMAT(delta.y) + ") px";
+ } else if (drag_type == DRAG_MOVE_X) {
+ transform_message = TTR("Moving:") + " " + FORMAT(delta.x) + " px";
+ } else if (drag_type == DRAG_MOVE_Y) {
+ transform_message = TTR("Moving:") + " " + FORMAT(delta.y) + " px";
+ }
+ } break;
+
+ case DRAG_ROTATE: {
+ real_t delta = Math::rad2deg(current_transform.get_rotation() - original_transform.get_rotation());
+ transform_message = TTR("Rotating:") + " " + FORMAT(delta) + String::utf8(" °");
+ } break;
+
+ case DRAG_SCALE_X:
+ case DRAG_SCALE_Y:
+ case DRAG_SCALE_BOTH: {
+ Vector2 original_scale = (Math::is_zero_approx(original_transform.get_scale().x) || Math::is_zero_approx(original_transform.get_scale().y)) ? Vector2(CMP_EPSILON, CMP_EPSILON) : original_transform.get_scale();
+ Vector2 delta = current_transform.get_scale() / original_scale;
+ if (drag_type == DRAG_SCALE_BOTH) {
+ transform_message = TTR("Scaling:") + String::utf8(" ×(") + FORMAT(delta.x) + ", " + FORMAT(delta.y) + ")";
+ } else if (drag_type == DRAG_SCALE_X) {
+ transform_message = TTR("Scaling:") + String::utf8(" ×") + FORMAT(delta.x);
+ } else if (drag_type == DRAG_SCALE_Y) {
+ transform_message = TTR("Scaling:") + String::utf8(" ×") + FORMAT(delta.y);
+ }
+ } break;
+
+ default:
+ break;
+ }
+#undef FORMAT
+
+ if (transform_message.is_empty()) {
+ return;
+ }
+
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Point2 msgpos = Point2(RULER_WIDTH + 5 * EDSCALE, viewport->get_size().y - 20 * EDSCALE);
+ viewport->draw_string(font, msgpos + Point2(1, 1), transform_message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
+ viewport->draw_string(font, msgpos + Point2(-1, -1), transform_message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
+ viewport->draw_string(font, msgpos, transform_message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 1));
+}
+
void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
ERR_FAIL_COND(!p_node);
@@ -3735,6 +3816,7 @@ void CanvasItemEditor::_draw_viewport() {
_draw_smart_snapping();
_draw_focus();
_draw_hover();
+ _draw_transform_message();
}
void CanvasItemEditor::update_viewport() {
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index c20a054800..5f50882dba 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -347,6 +347,7 @@ private:
bool is_hovering_v_guide = false;
bool updating_value_dialog = false;
+ Transform2D original_transform;
Point2 box_selecting_to;
@@ -433,6 +434,7 @@ private:
void _draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
void _draw_hover();
+ void _draw_transform_message();
void _draw_viewport();
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 6d1a86765a..66e58339ed 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -751,12 +751,13 @@ void CurveEditor::_draw() {
// Help text
+ float width = view_size.x - 60 * EDSCALE;
if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
text_color.a *= 0.4;
- draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
+ draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), HORIZONTAL_ALIGNMENT_LEFT, width, -1, font_size, text_color);
} else if (curve.get_point_count() == 0) {
text_color.a *= 0.4;
- draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color);
+ draw_multiline_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), HORIZONTAL_ALIGNMENT_LEFT, width, -1, font_size, text_color);
}
}
@@ -840,9 +841,5 @@ Ref<Texture2D> CurvePreviewGenerator::generate(const Ref<Resource> &p_from, cons
prev_y = y;
}
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
-
- ptex->create_from_image(img_ref);
- return ptex;
+ return ImageTexture::create_from_image(img_ref);
}
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index bb0cfcba25..478f4264e5 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -127,13 +127,9 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const Ref<Resource> &p_from,
}
Vector2i new_size_i(MAX(1, (int)new_size.x), MAX(1, (int)new_size.y));
img->resize(new_size_i.x, new_size_i.y, Image::INTERPOLATE_CUBIC);
-
post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
-
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
@@ -171,14 +167,9 @@ Ref<Texture2D> EditorImagePreviewPlugin::generate(const Ref<Resource> &p_from, c
new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
-
post_process_preview(img);
- Ref<ImageTexture> ptex;
- ptex.instantiate();
-
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
EditorImagePreviewPlugin::EditorImagePreviewPlugin() {
@@ -239,13 +230,9 @@ Ref<Texture2D> EditorBitmapPreviewPlugin::generate(const Ref<Resource> &p_from,
new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
-
post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
-
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
bool EditorBitmapPreviewPlugin::generate_small_preview_automatically() const {
@@ -282,11 +269,8 @@ Ref<Texture2D> EditorPackedScenePreviewPlugin::generate_from_path(const String &
img.instantiate();
Error err = img->load(path);
if (err == OK) {
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
-
post_process_preview(img);
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
} else {
return Ref<Texture2D>();
@@ -336,9 +320,7 @@ Ref<Texture2D> EditorMaterialPreviewPlugin::generate(const Ref<Resource> &p_from
int thumbnail_size = MAX(p_size.x, p_size.y);
img->resize(thumbnail_size, thumbnail_size, Image::INTERPOLATE_CUBIC);
post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
return Ref<Texture2D>();
@@ -591,13 +573,8 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
}
}
}
-
post_process_preview(img);
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
-
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
@@ -676,12 +653,10 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const Ref<Resource> &p_f
//post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
Ref<Image> image;
image.instantiate();
image->create(w, h, false, Image::FORMAT_RGB8, img);
- ptex->create_from_image(image);
- return ptex;
+ return ImageTexture::create_from_image(image);
}
EditorAudioStreamPreviewPlugin::EditorAudioStreamPreviewPlugin() {
@@ -746,12 +721,9 @@ Ref<Texture2D> EditorMeshPreviewPlugin::generate(const Ref<Resource> &p_from, co
new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
-
post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
- ptex->create_from_image(img);
- return ptex;
+ return ImageTexture::create_from_image(img);
}
EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
@@ -812,19 +784,12 @@ void EditorFontPreviewPlugin::_preview_done() {
}
bool EditorFontPreviewPlugin::handles(const String &p_type) const {
- return ClassDB::is_parent_class(p_type, "FontData") || ClassDB::is_parent_class(p_type, "Font");
+ return ClassDB::is_parent_class(p_type, "Font");
}
Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const {
- Ref<Resource> res = ResourceLoader::load(p_path);
- ERR_FAIL_COND_V(res.is_null(), Ref<Texture2D>());
- Ref<Font> sampled_font;
- if (res->is_class("Font")) {
- sampled_font = res->duplicate();
- } else if (res->is_class("FontData")) {
- sampled_font.instantiate();
- sampled_font->add_data(res->duplicate());
- }
+ Ref<Font> sampled_font = ResourceLoader::load(p_path);
+ ERR_FAIL_COND_V(sampled_font.is_null(), Ref<Texture2D>());
String sample;
static const String sample_base = U"12漢字ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš áœ€áœ á€á áž€á  á¤á¥Ab😀";
@@ -836,18 +801,16 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
if (sample.is_empty()) {
sample = sampled_font->get_supported_chars().substr(0, 6);
}
- Vector2 size = sampled_font->get_string_size(sample, 50);
+ Vector2 size = sampled_font->get_string_size(sample, HORIZONTAL_ALIGNMENT_LEFT, -1, 50);
Vector2 pos;
pos.x = 64 - size.x / 2;
pos.y = 80;
- Ref<Font> font = sampled_font;
-
const Color c = GLOBAL_GET("rendering/environment/defaults/default_clear_color");
const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0;
- font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
+ sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg));
RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT);
@@ -868,13 +831,9 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y);
}
img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC);
-
post_process_preview(img);
- Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
- ptex->create_from_image(img);
-
- return ptex;
+ return ImageTexture::create_from_image(img);
}
Ref<Texture2D> EditorFontPreviewPlugin::generate(const Ref<Resource> &p_from, const Size2 &p_size) const {
@@ -924,11 +883,7 @@ Ref<Texture2D> EditorGradientPreviewPlugin::generate(const Ref<Resource> &p_from
ptex.instantiate();
ptex->set_width(p_size.width * GRADIENT_PREVIEW_TEXTURE_SCALE_FACTOR * EDSCALE);
ptex->set_gradient(gradient);
-
- Ref<ImageTexture> itex;
- itex.instantiate();
- itex->create_from_image(ptex->get_image());
- return itex;
+ return ImageTexture::create_from_image(ptex->get_image());
}
return Ref<Texture2D>();
}
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
new file mode 100644
index 0000000000..848fb5887d
--- /dev/null
+++ b/editor/plugins/font_config_plugin.cpp
@@ -0,0 +1,979 @@
+/*************************************************************************/
+/* font_config_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "font_config_plugin.h"
+
+#include "editor/editor_scale.h"
+#include "editor/import/dynamic_font_import_settings.h"
+
+/*************************************************************************/
+/* EditorPropertyFontMetaObject */
+/*************************************************************************/
+
+bool EditorPropertyFontMetaObject::_set(const StringName &p_name, const Variant &p_value) {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ String key = name.get_slicec('/', 1);
+ dict[key] = p_value;
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorPropertyFontMetaObject::_get(const StringName &p_name, Variant &r_ret) const {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ String key = name.get_slicec('/', 1);
+ r_ret = dict[key];
+ return true;
+ }
+
+ return false;
+}
+
+void EditorPropertyFontMetaObject::_bind_methods() {
+}
+
+void EditorPropertyFontMetaObject::set_dict(const Dictionary &p_dict) {
+ dict = p_dict;
+}
+
+Dictionary EditorPropertyFontMetaObject::get_dict() {
+ return dict;
+}
+
+/*************************************************************************/
+/* EditorPropertyFontOTObject */
+/*************************************************************************/
+
+bool EditorPropertyFontOTObject::_set(const StringName &p_name, const Variant &p_value) {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ int key = name.get_slicec('/', 1).to_int();
+ dict[key] = p_value;
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorPropertyFontOTObject::_get(const StringName &p_name, Variant &r_ret) const {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ int key = name.get_slicec('/', 1).to_int();
+ r_ret = dict[key];
+ return true;
+ }
+
+ return false;
+}
+
+void EditorPropertyFontOTObject::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorPropertyFontOTObject::property_can_revert);
+ ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorPropertyFontOTObject::property_get_revert);
+}
+
+void EditorPropertyFontOTObject::set_dict(const Dictionary &p_dict) {
+ dict = p_dict;
+}
+
+Dictionary EditorPropertyFontOTObject::get_dict() {
+ return dict;
+}
+
+void EditorPropertyFontOTObject::set_defaults(const Dictionary &p_dict) {
+ defaults_dict = p_dict;
+}
+
+Dictionary EditorPropertyFontOTObject::get_defaults() {
+ return defaults_dict;
+}
+
+bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ int key = name.get_slicec('/', 1).to_int();
+ if (defaults_dict.has(key) && dict.has(key)) {
+ int value = dict[key];
+ Vector3i range = defaults_dict[key];
+ return range.z != value;
+ }
+ }
+
+ return false;
+}
+
+Variant EditorPropertyFontOTObject::property_get_revert(const String &p_name) {
+ String name = p_name;
+
+ if (name.begins_with("keys")) {
+ int key = name.get_slicec('/', 1).to_int();
+ if (defaults_dict.has(key)) {
+ Vector3i range = defaults_dict[key];
+ return range.z;
+ }
+ }
+
+ return Variant();
+}
+
+/*************************************************************************/
+/* EditorPropertyFontMetaOverride */
+/*************************************************************************/
+
+void EditorPropertyFontMetaOverride::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ if (Object::cast_to<Button>(button_add)) {
+ button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ }
+ } break;
+ }
+}
+
+void EditorPropertyFontMetaOverride::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ if (p_property.begins_with("keys")) {
+ Dictionary dict = object->get_dict();
+ String key = p_property.get_slice("/", 1);
+ dict[key] = (bool)p_value;
+
+ emit_changed(get_edited_property(), dict, "", true);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyFontMetaOverride::_remove(Object *p_button, const String &p_key) {
+ Dictionary dict = object->get_dict();
+
+ dict.erase(p_key);
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyFontMetaOverride::_add_menu() {
+ if (script_editor) {
+ Size2 size = get_size();
+ menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
+ menu->reset_size();
+ menu->popup();
+ } else {
+ locale_select->popup_locale_dialog();
+ }
+}
+
+void EditorPropertyFontMetaOverride::_add_script(int p_option) {
+ Dictionary dict = object->get_dict();
+
+ dict[script_codes[p_option]] = true;
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyFontMetaOverride::_add_lang(const String &p_locale) {
+ Dictionary dict = object->get_dict();
+
+ dict[p_locale] = true;
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyFontMetaOverride::_object_id_selected(const StringName &p_property, ObjectID p_id) {
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
+}
+
+void EditorPropertyFontMetaOverride::update_property() {
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ Dictionary dict = updated_val;
+
+ edit->set_text(vformat(TTR("Overrides (%d)"), dict.size()));
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+ updating = true;
+
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_v_size_flags(SIZE_EXPAND_FILL);
+ container->add_child(vbox);
+
+ property_vbox = memnew(VBoxContainer);
+ property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbox->add_child(property_vbox);
+
+ paginator = memnew(EditorPaginator);
+ paginator->connect("page_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_page_changed));
+ vbox->add_child(paginator);
+ } else {
+ // Queue children for deletion, deleting immediately might cause errors.
+ for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
+ property_vbox->get_child(i)->queue_delete();
+ }
+ button_add = nullptr;
+ }
+
+ int size = dict.size();
+
+ int max_page = MAX(0, size - 1) / page_length;
+ page_index = MIN(page_index, max_page);
+
+ paginator->update(page_index, max_page);
+ paginator->set_visible(max_page > 0);
+
+ int offset = page_index * page_length;
+
+ int amount = MIN(size - offset, page_length);
+
+ dict = dict.duplicate();
+ object->set_dict(dict);
+
+ for (int i = 0; i < amount; i++) {
+ String name = dict.get_key_at_index(i);
+ EditorProperty *prop = memnew(EditorPropertyCheck);
+ prop->set_object_and_property(object.ptr(), "keys/" + name);
+
+ if (script_editor) {
+ prop->set_label(TranslationServer::get_singleton()->get_script_name(name));
+ } else {
+ prop->set_label(TranslationServer::get_singleton()->get_locale_name(name));
+ }
+ prop->set_tooltip(name);
+ prop->set_selectable(false);
+
+ prop->connect("property_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_property_changed));
+ prop->connect("object_id_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_object_id_selected));
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ property_vbox->add_child(hbox);
+ hbox->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *remove = memnew(Button);
+ remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ hbox->add_child(remove);
+ remove->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_remove), varray(remove, name));
+
+ prop->update_property();
+ }
+
+ if (script_editor) {
+ button_add = EditorInspector::create_inspector_action_button(TTR("Add Script"));
+ } else {
+ button_add = EditorInspector::create_inspector_action_button(TTR("Add Locale"));
+ }
+ button_add->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_menu));
+ property_vbox->add_child(button_add);
+
+ updating = false;
+ } else {
+ if (container) {
+ set_bottom_editor(nullptr);
+ memdelete(container);
+ button_add = nullptr;
+ container = nullptr;
+ }
+ }
+}
+
+void EditorPropertyFontMetaOverride::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Callable::CallError ce;
+ Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyFontMetaOverride::_page_changed(int p_page) {
+ if (updating) {
+ return;
+ }
+ page_index = p_page;
+ update_property();
+}
+
+EditorPropertyFontMetaOverride::EditorPropertyFontMetaOverride(bool p_script) {
+ script_editor = p_script;
+
+ object.instantiate();
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+
+ edit = memnew(Button);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_edit_pressed));
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+
+ menu = memnew(PopupMenu);
+ if (script_editor) {
+ script_codes = TranslationServer::get_singleton()->get_all_scripts();
+ for (int i = 0; i < script_codes.size(); i++) {
+ menu->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i);
+ }
+ }
+ add_child(menu);
+ menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_script));
+
+ locale_select = memnew(EditorLocaleDialog);
+ locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_add_lang));
+ add_child(locale_select);
+}
+
+/*************************************************************************/
+/* EditorPropertyOTVariation */
+/*************************************************************************/
+
+void EditorPropertyOTVariation::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ } break;
+ }
+}
+
+void EditorPropertyOTVariation::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ if (p_property.begins_with("keys")) {
+ Dictionary dict = object->get_dict();
+ Dictionary defaults_dict = object->get_defaults();
+ int key = p_property.get_slice("/", 1).to_int();
+ dict[key] = (int)p_value;
+ if (defaults_dict.has(key)) {
+ Vector3i range = defaults_dict[key];
+ if (range.z == (int)p_value) {
+ dict.erase(key);
+ }
+ }
+
+ emit_changed(get_edited_property(), dict, "", true);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyOTVariation::_object_id_selected(const StringName &p_property, ObjectID p_id) {
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
+}
+
+void EditorPropertyOTVariation::update_property() {
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ Dictionary dict = updated_val;
+
+ Ref<Font> fd;
+ if (Object::cast_to<Font>(get_edited_object()) != nullptr) {
+ fd = get_edited_object();
+ } else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) {
+ Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object());
+ fd = imp->get_font();
+ }
+
+ Dictionary supported = (fd.is_valid()) ? fd->get_supported_variation_list() : Dictionary();
+
+ edit->set_text(vformat(TTR("Variation Coordinates (%d)"), supported.size()));
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+ updating = true;
+
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_v_size_flags(SIZE_EXPAND_FILL);
+ container->add_child(vbox);
+
+ property_vbox = memnew(VBoxContainer);
+ property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbox->add_child(property_vbox);
+
+ paginator = memnew(EditorPaginator);
+ paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTVariation::_page_changed));
+ vbox->add_child(paginator);
+ } else {
+ // Queue children for deletion, deleting immediately might cause errors.
+ for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
+ property_vbox->get_child(i)->queue_delete();
+ }
+ }
+
+ int size = supported.size();
+
+ int max_page = MAX(0, size - 1) / page_length;
+ page_index = MIN(page_index, max_page);
+
+ paginator->update(page_index, max_page);
+ paginator->set_visible(max_page > 0);
+
+ int offset = page_index * page_length;
+
+ int amount = MIN(size - offset, page_length);
+
+ dict = dict.duplicate();
+ object->set_dict(dict);
+ object->set_defaults(supported);
+
+ for (int i = 0; i < amount; i++) {
+ int name_tag = supported.get_key_at_index(i);
+ Vector3i range = supported.get_value_at_index(i);
+
+ EditorPropertyInteger *prop = memnew(EditorPropertyInteger);
+ prop->setup(range.x, range.y, 1, false, false);
+ prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
+
+ String name = TS->tag_to_name(name_tag);
+ prop->set_label(name.capitalize());
+ prop->set_tooltip(name);
+ prop->set_selectable(false);
+
+ prop->connect("property_changed", callable_mp(this, &EditorPropertyOTVariation::_property_changed));
+ prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTVariation::_object_id_selected));
+
+ property_vbox->add_child(prop);
+
+ prop->update_property();
+ }
+
+ updating = false;
+ } else {
+ if (container) {
+ set_bottom_editor(nullptr);
+ memdelete(container);
+ container = nullptr;
+ }
+ }
+}
+
+void EditorPropertyOTVariation::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Callable::CallError ce;
+ Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyOTVariation::_page_changed(int p_page) {
+ if (updating) {
+ return;
+ }
+ page_index = p_page;
+ update_property();
+}
+
+EditorPropertyOTVariation::EditorPropertyOTVariation() {
+ object.instantiate();
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+
+ edit = memnew(Button);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyOTVariation::_edit_pressed));
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+}
+
+/*************************************************************************/
+/* EditorPropertyOTFeatures */
+/*************************************************************************/
+
+void EditorPropertyOTFeatures::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ if (Object::cast_to<Button>(button_add)) {
+ button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ }
+ } break;
+ }
+}
+
+void EditorPropertyOTFeatures::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ if (p_property.begins_with("keys")) {
+ Dictionary dict = object->get_dict();
+ int key = p_property.get_slice("/", 1).to_int();
+ dict[key] = (int)p_value;
+
+ emit_changed(get_edited_property(), dict, "", true);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyOTFeatures::_remove(Object *p_button, int p_key) {
+ Dictionary dict = object->get_dict();
+
+ dict.erase(p_key);
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyOTFeatures::_add_menu() {
+ Size2 size = get_size();
+ menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
+ menu->reset_size();
+ menu->popup();
+}
+
+void EditorPropertyOTFeatures::_add_feature(int p_option) {
+ Dictionary dict = object->get_dict();
+
+ dict[p_option] = 1;
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyOTFeatures::_object_id_selected(const StringName &p_property, ObjectID p_id) {
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
+}
+
+void EditorPropertyOTFeatures::update_property() {
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ Dictionary dict = updated_val;
+
+ Ref<Font> fd;
+ if (Object::cast_to<FontVariation>(get_edited_object()) != nullptr) {
+ fd = get_edited_object();
+ } else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) {
+ Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object());
+ fd = imp->get_font();
+ }
+
+ Dictionary supported;
+ if (fd.is_valid()) {
+ supported = fd->get_supported_feature_list();
+ }
+
+ edit->set_text(vformat(TTR("Features (%d of %d set)"), dict.size(), supported.size()));
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+ updating = true;
+
+ if (!container) {
+ container = memnew(MarginContainer);
+ container->set_theme_type_variation("MarginContainer4px");
+ add_child(container);
+ set_bottom_editor(container);
+
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_v_size_flags(SIZE_EXPAND_FILL);
+ container->add_child(vbox);
+
+ property_vbox = memnew(VBoxContainer);
+ property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbox->add_child(property_vbox);
+
+ paginator = memnew(EditorPaginator);
+ paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTFeatures::_page_changed));
+ vbox->add_child(paginator);
+ } else {
+ // Queue children for deletion, deleting immediately might cause errors.
+ for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
+ property_vbox->get_child(i)->queue_delete();
+ }
+ button_add = nullptr;
+ }
+
+ // Update add menu items.
+ menu->clear();
+ bool have_sub[FGRP_MAX];
+ for (int i = 0; i < FGRP_MAX; i++) {
+ menu_sub[i]->clear();
+ have_sub[i] = false;
+ }
+
+ bool show_hidden = EDITOR_GET("interface/inspector/show_low_level_opentype_features");
+
+ for (int i = 0; i < supported.size(); i++) {
+ int name_tag = supported.get_key_at_index(i);
+ Dictionary info = supported.get_value_at_index(i);
+ bool hidden = info["hidden"].operator bool();
+ String name = TS->tag_to_name(name_tag);
+ FeatureGroups grp = FGRP_MAX;
+
+ if (hidden && !show_hidden) {
+ continue;
+ }
+
+ if (name.begins_with("stylistic_set_")) {
+ grp = FGRP_STYLISTIC_SET;
+ } else if (name.begins_with("character_variant_")) {
+ grp = FGRP_CHARACTER_VARIANT;
+ } else if (name.ends_with("_capitals")) {
+ grp = FGRP_CAPITLS;
+ } else if (name.ends_with("_ligatures")) {
+ grp = FGRP_LIGATURES;
+ } else if (name.ends_with("_alternates")) {
+ grp = FGRP_ALTERNATES;
+ } else if (name.ends_with("_kanji_forms") || name.begins_with("jis") || name == "simplified_forms" || name == "traditional_name_forms" || name == "traditional_forms") {
+ grp = FGRP_EAL;
+ } else if (name.ends_with("_widths")) {
+ grp = FGRP_EAW;
+ } else if (name == "tabular_figures" || name == "proportional_figures") {
+ grp = FGRP_NUMAL;
+ } else if (name.begins_with("custom_")) {
+ grp = FGRP_CUSTOM;
+ }
+ String disp_name = name.capitalize();
+ if (info.has("label")) {
+ disp_name = vformat("%s (%s)", disp_name, info["label"].operator String());
+ }
+
+ if (grp == FGRP_MAX) {
+ menu->add_item(disp_name, name_tag);
+ } else {
+ menu_sub[grp]->add_item(disp_name, name_tag);
+ have_sub[grp] = true;
+ }
+ }
+ for (int i = 0; i < FGRP_MAX; i++) {
+ if (have_sub[i]) {
+ menu->add_submenu_item(RTR(group_names[i]), "FTRMenu_" + itos(i));
+ }
+ }
+
+ int size = dict.size();
+
+ int max_page = MAX(0, size - 1) / page_length;
+ page_index = MIN(page_index, max_page);
+
+ paginator->update(page_index, max_page);
+ paginator->set_visible(max_page > 0);
+
+ int offset = page_index * page_length;
+
+ int amount = MIN(size - offset, page_length);
+
+ dict = dict.duplicate();
+ object->set_dict(dict);
+
+ for (int i = 0; i < amount; i++) {
+ int name_tag = dict.get_key_at_index(i);
+
+ if (supported.has(name_tag)) {
+ Dictionary info = supported[name_tag];
+ Variant::Type vtype = Variant::Type(info["type"].operator int());
+ bool hidden = info["hidden"].operator bool();
+ if (hidden && !show_hidden) {
+ continue;
+ }
+
+ EditorProperty *prop = nullptr;
+ switch (vtype) {
+ case Variant::NIL: {
+ prop = memnew(EditorPropertyNil);
+ } break;
+ case Variant::BOOL: {
+ prop = memnew(EditorPropertyCheck);
+ } break;
+ case Variant::INT: {
+ EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
+ editor->setup(0, 255, 1, false, false);
+ prop = editor;
+ } break;
+ default: {
+ ERR_CONTINUE_MSG(true, vformat("Unsupported OT feature data type %s", Variant::get_type_name(vtype)));
+ }
+ }
+ prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
+
+ String name = TS->tag_to_name(name_tag);
+ String disp_name = name.capitalize();
+ if (info.has("label")) {
+ disp_name = vformat("%s (%s)", disp_name, info["label"].operator String());
+ }
+ prop->set_label(disp_name);
+ prop->set_tooltip(name);
+ prop->set_selectable(false);
+
+ prop->connect("property_changed", callable_mp(this, &EditorPropertyOTFeatures::_property_changed));
+ prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTFeatures::_object_id_selected));
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ property_vbox->add_child(hbox);
+ hbox->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *remove = memnew(Button);
+ remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ hbox->add_child(remove);
+ remove->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_remove), varray(remove, name_tag));
+
+ prop->update_property();
+ }
+ }
+
+ button_add = EditorInspector::create_inspector_action_button(TTR("Add Feature"));
+ button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button_add->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_menu));
+ property_vbox->add_child(button_add);
+
+ updating = false;
+ } else {
+ if (container) {
+ set_bottom_editor(nullptr);
+ memdelete(container);
+ button_add = nullptr;
+ container = nullptr;
+ }
+ }
+}
+
+void EditorPropertyOTFeatures::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Callable::CallError ce;
+ Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyOTFeatures::_page_changed(int p_page) {
+ if (updating) {
+ return;
+ }
+ page_index = p_page;
+ update_property();
+}
+
+EditorPropertyOTFeatures::EditorPropertyOTFeatures() {
+ object.instantiate();
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+
+ edit = memnew(Button);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_edit_pressed));
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+
+ menu = memnew(PopupMenu);
+ add_child(menu);
+ menu->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature));
+
+ for (int i = 0; i < FGRP_MAX; i++) {
+ menu_sub[i] = memnew(PopupMenu);
+ menu_sub[i]->set_name("FTRMenu_" + itos(i));
+ menu->add_child(menu_sub[i]);
+ menu_sub[i]->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature));
+ }
+
+ group_names[FGRP_STYLISTIC_SET] = "Stylistic Sets";
+ group_names[FGRP_CHARACTER_VARIANT] = "Character Variants";
+ group_names[FGRP_CAPITLS] = "Capitals";
+ group_names[FGRP_LIGATURES] = "Ligatures";
+ group_names[FGRP_ALTERNATES] = "Alternates";
+ group_names[FGRP_EAL] = "East Asian Language";
+ group_names[FGRP_EAW] = "East Asian Widths";
+ group_names[FGRP_NUMAL] = "Numeral Alignment";
+ group_names[FGRP_CUSTOM] = "Custom";
+}
+
+/*************************************************************************/
+/* EditorInspectorPluginFontVariation */
+/*************************************************************************/
+
+bool EditorInspectorPluginFontVariation::can_handle(Object *p_object) {
+ return (Object::cast_to<FontVariation>(p_object) != nullptr) || (Object::cast_to<DynamicFontImportSettingsData>(p_object) != nullptr);
+}
+
+bool EditorInspectorPluginFontVariation::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
+ if (p_path == "variation_opentype") {
+ add_property_editor(p_path, memnew(EditorPropertyOTVariation));
+ return true;
+ } else if (p_path == "opentype_features") {
+ add_property_editor(p_path, memnew(EditorPropertyOTFeatures));
+ return true;
+ } else if (p_path == "language_support") {
+ add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(false)));
+ return true;
+ } else if (p_path == "script_support") {
+ add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(true)));
+ return true;
+ }
+ return false;
+}
+
+/*************************************************************************/
+/* FontPreview */
+/*************************************************************************/
+
+void FontPreview::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_DRAW: {
+ // Draw font name (style).
+ Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
+ font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color);
+
+ // Draw font preview.
+ Vector2 pos = Vector2(0, font->get_height(font_size)) + (get_size() - Vector2(0, font->get_height(font_size)) - line->get_size()) / 2;
+ line->draw(get_canvas_item(), pos, text_color);
+
+ // Draw font baseline.
+ Color line_color = text_color;
+ line_color.a *= 0.6;
+ draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color);
+ draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color);
+ } break;
+ }
+}
+
+void FontPreview::_bind_methods() {}
+
+Size2 FontPreview::get_minimum_size() const {
+ return Vector2(64, 64) * EDSCALE;
+}
+
+void FontPreview::set_data(const Ref<Font> &p_f) {
+ line->clear();
+ if (p_f.is_valid()) {
+ name = vformat("%s (%s)", p_f->get_font_name(), p_f->get_font_style_name());
+ if (p_f->is_class("FontVariation")) {
+ name += " " + TTR(" - Variation");
+ }
+ String sample;
+ static const String sample_base = U"12漢字ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš áœ€áœ á€á áž€á  á¤á¥Ab😀";
+ for (int i = 0; i < sample_base.length(); i++) {
+ if (p_f->has_char(sample_base[i])) {
+ sample += sample_base[i];
+ }
+ }
+ if (sample.is_empty()) {
+ sample = p_f->get_supported_chars().substr(0, 6);
+ }
+ line->add_string(sample, p_f, 50);
+ }
+
+ update();
+}
+
+FontPreview::FontPreview() {
+ line.instantiate();
+}
+
+/*************************************************************************/
+/* EditorInspectorPluginFontPreview */
+/*************************************************************************/
+
+bool EditorInspectorPluginFontPreview::can_handle(Object *p_object) {
+ return Object::cast_to<Font>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginFontPreview::parse_begin(Object *p_object) {
+ Font *fd = Object::cast_to<Font>(p_object);
+ ERR_FAIL_COND(!fd);
+
+ FontPreview *editor = memnew(FontPreview);
+ editor->set_data(fd);
+ add_custom_control(editor);
+}
+
+bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
+ return false;
+}
+
+/*************************************************************************/
+/* FontEditorPlugin */
+/*************************************************************************/
+
+FontEditorPlugin::FontEditorPlugin() {
+ Ref<EditorInspectorPluginFontVariation> fc_plugin;
+ fc_plugin.instantiate();
+ EditorInspector::add_inspector_plugin(fc_plugin);
+
+ Ref<EditorInspectorPluginFontPreview> fp_plugin;
+ fp_plugin.instantiate();
+ EditorInspector::add_inspector_plugin(fp_plugin);
+}
diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h
new file mode 100644
index 0000000000..9b7ee55870
--- /dev/null
+++ b/editor/plugins/font_config_plugin.h
@@ -0,0 +1,261 @@
+/*************************************************************************/
+/* font_config_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OT_FEATURES_PLUGIN_H
+#define OT_FEATURES_PLUGIN_H
+
+#include "core/io/marshalls.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_properties.h"
+
+/*************************************************************************/
+
+class EditorPropertyFontMetaObject : public RefCounted {
+ GDCLASS(EditorPropertyFontMetaObject, RefCounted);
+
+ Dictionary dict;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ static void _bind_methods();
+
+public:
+ void set_dict(const Dictionary &p_dict);
+ Dictionary get_dict();
+
+ EditorPropertyFontMetaObject(){};
+};
+
+/*************************************************************************/
+
+class EditorPropertyFontOTObject : public RefCounted {
+ GDCLASS(EditorPropertyFontOTObject, RefCounted);
+
+ Dictionary dict;
+ Dictionary defaults_dict;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ static void _bind_methods();
+
+public:
+ void set_dict(const Dictionary &p_dict);
+ Dictionary get_dict();
+
+ void set_defaults(const Dictionary &p_dict);
+ Dictionary get_defaults();
+
+ bool property_can_revert(const String &p_name);
+ Variant property_get_revert(const String &p_name);
+
+ EditorPropertyFontOTObject(){};
+};
+
+/*************************************************************************/
+
+class EditorPropertyFontMetaOverride : public EditorProperty {
+ GDCLASS(EditorPropertyFontMetaOverride, EditorProperty);
+
+ Ref<EditorPropertyFontMetaObject> object;
+
+ MarginContainer *container = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+
+ Button *button_add = nullptr;
+ Button *edit = nullptr;
+ PopupMenu *menu = nullptr;
+ EditorLocaleDialog *locale_select = nullptr;
+
+ Vector<String> script_codes;
+
+ bool script_editor = false;
+ bool updating = false;
+ int page_length = 20;
+ int page_index = 0;
+ EditorPaginator *paginator = nullptr;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods(){};
+
+ void _edit_pressed();
+ void _page_changed(int p_page);
+ void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+ void _remove(Object *p_button, const String &p_key);
+ void _add_menu();
+ void _add_script(int p_option);
+ void _add_lang(const String &p_locale);
+ void _object_id_selected(const StringName &p_property, ObjectID p_id);
+
+public:
+ virtual void update_property() override;
+
+ EditorPropertyFontMetaOverride(bool p_script);
+};
+
+/*************************************************************************/
+
+class EditorPropertyOTVariation : public EditorProperty {
+ GDCLASS(EditorPropertyOTVariation, EditorProperty);
+
+ Ref<EditorPropertyFontOTObject> object;
+
+ MarginContainer *container = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+
+ Button *edit = nullptr;
+
+ bool updating = false;
+ int page_length = 20;
+ int page_index = 0;
+ EditorPaginator *paginator = nullptr;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods(){};
+
+ void _edit_pressed();
+ void _page_changed(int p_page);
+ void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+ void _object_id_selected(const StringName &p_property, ObjectID p_id);
+
+public:
+ virtual void update_property() override;
+
+ EditorPropertyOTVariation();
+};
+
+/*************************************************************************/
+
+class EditorPropertyOTFeatures : public EditorProperty {
+ GDCLASS(EditorPropertyOTFeatures, EditorProperty);
+
+ enum FeatureGroups {
+ FGRP_STYLISTIC_SET,
+ FGRP_CHARACTER_VARIANT,
+ FGRP_CAPITLS,
+ FGRP_LIGATURES,
+ FGRP_ALTERNATES,
+ FGRP_EAL,
+ FGRP_EAW,
+ FGRP_NUMAL,
+ FGRP_CUSTOM,
+ FGRP_MAX,
+ };
+
+ Ref<EditorPropertyFontOTObject> object;
+
+ MarginContainer *container = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+
+ Button *button_add = nullptr;
+ Button *edit = nullptr;
+ PopupMenu *menu = nullptr;
+ PopupMenu *menu_sub[FGRP_MAX];
+ String group_names[FGRP_MAX];
+
+ bool updating = false;
+ int page_length = 20;
+ int page_index = 0;
+ EditorPaginator *paginator = nullptr;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods(){};
+
+ void _edit_pressed();
+ void _page_changed(int p_page);
+ void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+ void _remove(Object *p_button, int p_key);
+ void _add_menu();
+ void _add_feature(int p_option);
+ void _object_id_selected(const StringName &p_property, ObjectID p_id);
+
+public:
+ virtual void update_property() override;
+
+ EditorPropertyOTFeatures();
+};
+
+/*************************************************************************/
+
+class EditorInspectorPluginFontVariation : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginFontVariation, EditorInspectorPlugin);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
+};
+
+/*************************************************************************/
+
+class FontPreview : public Control {
+ GDCLASS(FontPreview, Control);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+ String name;
+ Ref<TextLine> line;
+
+public:
+ virtual Size2 get_minimum_size() const override;
+
+ void set_data(const Ref<Font> &p_f);
+
+ FontPreview();
+};
+
+/*************************************************************************/
+
+class EditorInspectorPluginFontPreview : public EditorInspectorPlugin {
+ GDCLASS(EditorInspectorPluginFontPreview, EditorInspectorPlugin);
+
+public:
+ virtual bool can_handle(Object *p_object) override;
+ virtual void parse_begin(Object *p_object) override;
+ virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
+};
+
+/*************************************************************************/
+
+class FontEditorPlugin : public EditorPlugin {
+ GDCLASS(FontEditorPlugin, EditorPlugin);
+
+public:
+ FontEditorPlugin();
+
+ virtual String get_name() const override { return "Font"; }
+};
+
+#endif // OT_FEATURES_PLUGIN_H
diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp
deleted file mode 100644
index b9de621bcb..0000000000
--- a/editor/plugins/font_editor_plugin.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*************************************************************************/
-/* font_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "font_editor_plugin.h"
-
-#include "editor/editor_scale.h"
-
-void FontDataPreview::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_DRAW: {
- Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label"));
- Color line_color = text_color;
- line_color.a *= 0.6;
- Vector2 pos = (get_size() - line->get_size()) / 2;
- line->draw(get_canvas_item(), pos, text_color);
- draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color);
- draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color);
- } break;
- }
-}
-
-void FontDataPreview::_bind_methods() {}
-
-Size2 FontDataPreview::get_minimum_size() const {
- return Vector2(64, 64) * EDSCALE;
-}
-
-void FontDataPreview::set_data(const Ref<FontData> &p_data) {
- Ref<Font> f = memnew(Font);
- f->add_data(p_data);
-
- line->clear();
- if (p_data.is_valid()) {
- String sample;
- static const String sample_base = U"12漢字ԱբΑαÐбΑα×בابÜÜ’Þ€Þआআਆઆଆஆఆಆആආà¸à¸´àºàº´à¼€á€€á‚ áƒí•œê¸€áˆ€áŽ£áášáš áœ€áœ á€á áž€á  á¤á¥Ab😀";
- for (int i = 0; i < sample_base.length(); i++) {
- if (p_data->has_char(sample_base[i])) {
- sample += sample_base[i];
- }
- }
- if (sample.is_empty()) {
- sample = p_data->get_supported_chars().substr(0, 6);
- }
- line->add_string(sample, f, 72);
- }
-
- update();
-}
-
-FontDataPreview::FontDataPreview() {
- line.instantiate();
-}
-
-/*************************************************************************/
-
-bool EditorInspectorPluginFont::can_handle(Object *p_object) {
- return Object::cast_to<FontData>(p_object) != nullptr;
-}
-
-void EditorInspectorPluginFont::parse_begin(Object *p_object) {
- FontData *fd = Object::cast_to<FontData>(p_object);
- ERR_FAIL_COND(!fd);
-
- FontDataPreview *editor = memnew(FontDataPreview);
- editor->set_data(fd);
- add_custom_control(editor);
-}
-
-bool EditorInspectorPluginFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
- return false;
-}
-
-/*************************************************************************/
-
-FontEditorPlugin::FontEditorPlugin() {
- Ref<EditorInspectorPluginFont> fd_plugin;
- fd_plugin.instantiate();
- EditorInspector::add_inspector_plugin(fd_plugin);
-}
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 72caa15e9c..a255c12ed4 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -299,12 +299,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() {
img.instantiate();
img->create(w, h, false, Image::FORMAT_RGF, texdata);
-
- Ref<ImageTexture> imgt;
- imgt.instantiate();
- imgt->create_from_image(img);
-
- pm->set_emission_point_texture(imgt);
+ pm->set_emission_point_texture(ImageTexture::create_from_image(img));
pm->set_emission_point_count(vpc);
if (capture_colors) {
@@ -320,10 +315,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() {
img.instantiate();
img->create(w, h, false, Image::FORMAT_RGBA8, colordata);
-
- imgt.instantiate();
- imgt->create_from_image(img);
- pm->set_emission_color_texture(imgt);
+ pm->set_emission_color_texture(ImageTexture::create_from_image(img));
}
if (valid_normals.size()) {
@@ -343,10 +335,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() {
img.instantiate();
img->create(w, h, false, Image::FORMAT_RGF, normdata);
-
- imgt.instantiate();
- imgt->create_from_image(img);
- pm->set_emission_normal_texture(imgt);
+ pm->set_emission_normal_texture(ImageTexture::create_from_image(img));
} else {
pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS);
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index fa971679e6..5461fda58b 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -363,10 +363,7 @@ void GPUParticles3DEditor::_generate_emission_points() {
}
Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img));
-
- Ref<ImageTexture> tex;
- tex.instantiate();
- tex->create_from_image(image);
+ Ref<ImageTexture> tex = ImageTexture::create_from_image(image);
Ref<ParticlesMaterial> material = node->get_process_material();
ERR_FAIL_COND(material.is_null());
@@ -392,12 +389,7 @@ void GPUParticles3DEditor::_generate_emission_points() {
}
Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2));
-
- Ref<ImageTexture> tex2;
- tex2.instantiate();
- tex2->create_from_image(image2);
-
- material->set_emission_normal_texture(tex2);
+ material->set_emission_normal_texture(ImageTexture::create_from_image(image2));
} else {
material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS);
material->set_emission_point_count(point_count);
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 64aeb9f2a8..77cf1f0064 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -245,6 +245,7 @@ void EditorNode3DGizmo::Instance::create_instance(Node3D *p_base, bool p_hidden)
int layer = p_hidden ? 0 : 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER;
RS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26
RS::get_singleton()->instance_geometry_set_flag(instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
}
void EditorNode3DGizmo::add_mesh(const Ref<Mesh> &p_mesh, const Ref<Material> &p_material, const Transform3D &p_xform, const Ref<SkinReference> &p_skin_reference) {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 815d0a2425..99c492379d 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -145,7 +145,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) {
// Draw the axis letter for the positive axes.
const String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z");
- draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha));
+ draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha));
} else {
// Draw an outline around the negative axes.
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c);
@@ -2725,7 +2725,8 @@ static void draw_indicator_bar(Control &p_surface, real_t p_fill, const Ref<Text
p_surface.draw_texture(p_icon, icon_pos, p_color);
// Draw text below the bar (for speed/zoom information).
- p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color, Math::round(2 * EDSCALE), Color(0, 0, 0));
+ p_surface.draw_string_outline(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, Math::round(2 * EDSCALE), Color(0, 0, 0));
+ p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color);
}
void Node3DEditorViewport::_draw() {
@@ -3251,6 +3252,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i], layer);
RS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
move_plane_gizmo_instance[i] = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(move_plane_gizmo_instance[i], spatial_editor->get_move_plane_gizmo(i)->get_rid());
@@ -3259,6 +3261,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_plane_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(move_plane_gizmo_instance[i], layer);
RS::get_singleton()->instance_geometry_set_flag(move_plane_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(move_plane_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
rotate_gizmo_instance[i] = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(rotate_gizmo_instance[i], spatial_editor->get_rotate_gizmo(i)->get_rid());
@@ -3267,6 +3270,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer);
RS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
scale_gizmo_instance[i] = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid());
@@ -3275,6 +3279,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer);
RS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
scale_plane_gizmo_instance[i] = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(scale_plane_gizmo_instance[i], spatial_editor->get_scale_plane_gizmo(i)->get_rid());
@@ -3283,6 +3288,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_plane_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(scale_plane_gizmo_instance[i], layer);
RS::get_singleton()->instance_geometry_set_flag(scale_plane_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(scale_plane_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
axis_gizmo_instance[i] = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(axis_gizmo_instance[i], spatial_editor->get_axis_gizmo(i)->get_rid());
@@ -3290,6 +3296,8 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_set_visible(axis_gizmo_instance[i], true);
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(axis_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(axis_gizmo_instance[i], layer);
+ RS::get_singleton()->instance_geometry_set_flag(axis_gizmo_instance[i], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(axis_gizmo_instance[i], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
}
// Rotation white outline
@@ -3300,6 +3308,7 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[3], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[3], layer);
RS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[3], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[3], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
}
void Node3DEditorViewport::_finish_gizmo_instances() {
@@ -4514,6 +4523,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
vbox->add_child(view_menu);
display_submenu = memnew(PopupMenu);
+ view_menu->get_popup()->set_hide_on_checkable_item_selection(false);
view_menu->get_popup()->add_child(display_submenu);
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP);
@@ -4537,6 +4547,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_lighting", TTR("Display Lighting")), VIEW_DISPLAY_LIGHTING);
view_menu->get_popup()->add_radio_check_shortcut(ED_SHORTCUT("spatial_editor/view_display_unshaded", TTR("Display Unshaded")), VIEW_DISPLAY_SHADELESS);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL), true);
+ display_submenu->set_hide_on_checkable_item_selection(false);
display_submenu->add_radio_check_item(TTR("Directional Shadow Splits"), VIEW_DISPLAY_DEBUG_PSSM_SPLITS);
display_submenu->add_separator();
display_submenu->add_radio_check_item(TTR("Normal Buffer"), VIEW_DISPLAY_NORMAL_BUFFER);
@@ -4692,7 +4703,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
frame_time_gradient->add_point(0.5, Color());
top_right_vbox = memnew(VBoxContainer);
- top_right_vbox->set_anchors_and_offsets_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 2.0 * EDSCALE);
+ top_right_vbox->set_anchors_and_offsets_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 10.0 * EDSCALE);
top_right_vbox->set_h_grow_direction(GROW_DIRECTION_BEGIN);
// Make sure frame time labels don't touch the viewport's edge.
top_right_vbox->set_custom_minimum_size(Size2(100, 0) * EDSCALE);
@@ -5188,7 +5199,9 @@ Object *Node3DEditor::_get_editor_data(Object *p_what) {
RS::get_singleton()->instance_set_layer_mask(si->sbox_instance, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_set_layer_mask(si->sbox_instance_offset, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_offset, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_offset, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
si->sbox_instance_xray = RenderingServer::get_singleton()->instance_create2(
selection_box_xray->get_rid(),
sp->get_world_3d()->get_scenario());
@@ -5206,7 +5219,9 @@ Object *Node3DEditor::_get_editor_data(Object *p_what) {
RS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray_offset, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_xray, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_xray, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_xray_offset, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance_xray_offset, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
return si;
}
@@ -5993,6 +6008,7 @@ void fragment() {
origin_instance = RenderingServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER);
RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(origin_instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF);
}
@@ -6603,6 +6619,7 @@ void Node3DEditor::_init_grid() {
RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[c], RS::SHADOW_CASTING_SETTING_OFF);
RS::get_singleton()->instance_set_layer_mask(grid_instance[c], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER);
RS::get_singleton()->instance_geometry_set_flag(grid_instance[c], RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
+ RS::get_singleton()->instance_geometry_set_flag(grid_instance[c], RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
}
}
diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp
deleted file mode 100644
index f8526fb715..0000000000
--- a/editor/plugins/ot_features_plugin.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*************************************************************************/
-/* ot_features_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "ot_features_plugin.h"
-
-#include "scene/3d/label_3d.h"
-#include "scene/resources/primitive_meshes.h"
-
-void OpenTypeFeaturesEditor::_value_changed(double val) {
- if (setting) {
- return;
- }
-
- emit_changed(get_edited_property(), spin->get_value());
-}
-
-void OpenTypeFeaturesEditor::update_property() {
- double val = get_edited_object()->get(get_edited_property());
- setting = true;
- spin->set_value(val);
- setting = false;
-}
-
-void OpenTypeFeaturesEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
- case NOTIFICATION_THEME_CHANGED: {
- Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
-
- button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
- button->set_size(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))->get_size());
- spin->add_theme_color_override("label_color", base);
- } break;
- }
-}
-
-void OpenTypeFeaturesEditor::_remove_feature() {
- get_edited_object()->set(get_edited_property(), -1);
-}
-
-void OpenTypeFeaturesEditor::_bind_methods() {
-}
-
-OpenTypeFeaturesEditor::OpenTypeFeaturesEditor() {
- HBoxContainer *bc = memnew(HBoxContainer);
- add_child(bc);
-
- spin = memnew(EditorSpinSlider);
- spin->set_flat(true);
- bc->add_child(spin);
- add_focusable(spin);
- spin->connect("value_changed", callable_mp(this, &OpenTypeFeaturesEditor::_value_changed));
- spin->set_h_size_flags(SIZE_EXPAND_FILL);
-
- spin->set_min(0);
- spin->set_max(65536);
- spin->set_step(1);
- spin->set_hide_slider(false);
- spin->set_allow_greater(false);
- spin->set_allow_lesser(false);
-
- button = memnew(Button);
- button->set_tooltip(RTR("Remove feature"));
- button->set_flat(true);
- bc->add_child(button);
-
- button->connect("pressed", callable_mp(this, &OpenTypeFeaturesEditor::_remove_feature));
-
- setting = false;
-}
-
-/*************************************************************************/
-
-void OpenTypeFeaturesAdd::_add_feature(int p_option) {
- edited_object->set("opentype_features/" + TS->tag_to_name(p_option), 1);
-}
-
-void OpenTypeFeaturesAdd::_features_menu() {
- Size2 size = get_size();
- menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
- menu->reset_size();
- menu->popup();
-}
-
-void OpenTypeFeaturesAdd::setup(Object *p_object) {
- edited_object = p_object;
-
- menu->clear();
- menu_ss->clear();
- menu_cv->clear();
- menu_cu->clear();
- bool have_ss = false;
- bool have_cv = false;
- bool have_cu = false;
-
- Ref<Font> font;
-
- Control *ctrl = Object::cast_to<Control>(edited_object);
- if (ctrl != nullptr) {
- font = ctrl->get_theme_font(SNAME("font"));
- }
- Label3D *l3d = Object::cast_to<Label3D>(edited_object);
- if (l3d != nullptr) {
- font = l3d->_get_font_or_default();
- }
- TextMesh *tm = Object::cast_to<TextMesh>(edited_object);
- if (tm != nullptr) {
- font = tm->_get_font_or_default();
- }
-
- if (font.is_null()) {
- return;
- }
-
- Dictionary features = font->get_feature_list();
-
- for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) {
- String ftr_name = TS->tag_to_name(*ftr);
- if (ftr_name.begins_with("stylistic_set_")) {
- menu_ss->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- have_ss = true;
- } else if (ftr_name.begins_with("character_variant_")) {
- menu_cv->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- have_cv = true;
- } else if (ftr_name.begins_with("custom_")) {
- menu_cu->add_item(ftr_name.replace("custom_", ""), (int32_t)*ftr);
- have_cu = true;
- } else {
- menu->add_item(ftr_name.capitalize(), (int32_t)*ftr);
- }
- }
- if (have_ss) {
- menu->add_submenu_item(RTR("Stylistic Sets"), "SSMenu");
- }
- if (have_cv) {
- menu->add_submenu_item(RTR("Character Variants"), "CVMenu");
- }
- if (have_cu) {
- menu->add_submenu_item(RTR("Custom"), "CUMenu");
- }
-}
-
-void OpenTypeFeaturesAdd::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
- [[fallthrough]];
- }
- case NOTIFICATION_THEME_CHANGED: {
- set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
- } break;
- }
-}
-
-void OpenTypeFeaturesAdd::_bind_methods() {
-}
-
-OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
- set_text(TTR("Add Feature..."));
-
- menu = memnew(PopupMenu);
- add_child(menu);
-
- menu_cv = memnew(PopupMenu);
- menu_cv->set_name("CVMenu");
- menu->add_child(menu_cv);
-
- menu_ss = memnew(PopupMenu);
- menu_ss->set_name("SSMenu");
- menu->add_child(menu_ss);
-
- menu_cu = memnew(PopupMenu);
- menu_cu->set_name("CUMenu");
- menu->add_child(menu_cu);
-
- menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
- menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
- menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
- menu_cu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
-}
-
-/*************************************************************************/
-
-bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) {
- return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr) || (Object::cast_to<TextMesh>(p_object) != nullptr);
-}
-
-bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
- if (p_path == "opentype_features/_new") {
- OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd);
- editor->setup(p_object);
- add_custom_control(editor);
- return true;
- } else if (p_path.begins_with("opentype_features")) {
- OpenTypeFeaturesEditor *editor = memnew(OpenTypeFeaturesEditor);
- add_property_editor(p_path, editor);
- return true;
- }
- return false;
-}
-
-/*************************************************************************/
-
-OpenTypeFeaturesEditorPlugin::OpenTypeFeaturesEditorPlugin() {
- Ref<EditorInspectorPluginOpenTypeFeatures> ftr_plugin;
- ftr_plugin.instantiate();
- EditorInspector::add_inspector_plugin(ftr_plugin);
-}
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 7d4ffd1a25..66cd85a26a 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -886,6 +886,9 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
emit_signal(SNAME("go_to_help"), "class_enum:" + result.class_name + ":" + result.class_member);
} break;
+ case ScriptLanguage::LOOKUP_RESULT_CLASS_ANNOTATION: {
+ emit_signal(SNAME("go_to_help"), "class_annotation:" + result.class_name + ":" + result.class_member);
+ } break;
case ScriptLanguage::LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE: {
emit_signal(SNAME("go_to_help"), "class_global:" + result.class_name + ":" + result.class_member);
} break;
@@ -1862,11 +1865,7 @@ void ScriptTextEditor::_enable_code_editor() {
// get default color picker mode from editor settings
int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
- if (default_color_mode == 1) {
- color_picker->set_hsv_mode(true);
- } else if (default_color_mode == 2) {
- color_picker->set_raw_mode(true);
- }
+ color_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
diff --git a/editor/plugins/text_control_editor_plugin.cpp b/editor/plugins/text_control_editor_plugin.cpp
deleted file mode 100644
index 2a5faba4a2..0000000000
--- a/editor/plugins/text_control_editor_plugin.cpp
+++ /dev/null
@@ -1,660 +0,0 @@
-/*************************************************************************/
-/* text_control_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "text_control_editor_plugin.h"
-
-#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
-#include "editor/multi_node_edit.h"
-
-void TextControlEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) {
- EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts), make_binds(""));
- }
- [[fallthrough]];
- }
- case NOTIFICATION_THEME_CHANGED: {
- clear_formatting->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
- } break;
-
- case NOTIFICATION_EXIT_TREE: {
- if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) {
- EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts));
- }
- } break;
- }
-}
-
-void TextControlEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_update_control"), &TextControlEditor::_update_control);
-}
-
-void TextControlEditor::_find_resources(EditorFileSystemDirectory *p_dir) {
- for (int i = 0; i < p_dir->get_subdir_count(); i++) {
- _find_resources(p_dir->get_subdir(i));
- }
-
- for (int i = 0; i < p_dir->get_file_count(); i++) {
- if (p_dir->get_file_type(i) == "FontData") {
- Ref<FontData> fd = ResourceLoader::load(p_dir->get_file_path(i));
- if (fd.is_valid()) {
- String name = fd->get_font_name();
- String sty = fd->get_font_style_name();
- if (sty.is_empty()) {
- sty = "Default";
- }
- fonts[name][sty] = p_dir->get_file_path(i);
- }
- }
- }
-}
-
-void TextControlEditor::_reload_fonts(const String &p_path) {
- fonts.clear();
- _find_resources(EditorFileSystem::get_singleton()->get_filesystem());
- _update_control();
-}
-
-void TextControlEditor::_update_fonts_menu() {
- font_list->clear();
- font_list->add_item(TTR("[Theme Default]"), FONT_INFO_THEME_DEFAULT);
- if (custom_font.is_valid()) {
- font_list->add_item(TTR("[Custom Font]"), FONT_INFO_USER_CUSTOM);
- }
-
- int id = FONT_INFO_ID;
- for (const KeyValue<String, HashMap<String, String>> &E : fonts) {
- font_list->add_item(E.key, id++);
- }
-
- if (font_list->get_item_count() > 1) {
- font_list->show();
- } else {
- font_list->hide();
- }
-}
-
-void TextControlEditor::_update_styles_menu() {
- font_style_list->clear();
- if ((font_list->get_selected_id() >= FONT_INFO_ID)) {
- const String &name = font_list->get_item_text(font_list->get_selected());
- for (KeyValue<String, String> &E : fonts[name]) {
- font_style_list->add_item(E.key);
- }
- } else if (font_list->get_selected() >= 0) {
- font_style_list->add_item("Default");
- }
-
- if (font_style_list->get_item_count() > 1) {
- font_style_list->show();
- } else {
- font_style_list->hide();
- }
-}
-
-void TextControlEditor::_update_control() {
- if (!edited_controls.is_empty()) {
- String font_selected;
- bool same_font = true;
- String style_selected;
- bool same_style = true;
- int font_size = 0;
- bool same_font_size = true;
- int outline_size = 0;
- bool same_outline_size = true;
- Color font_color = Color{ 1.0f, 1.0f, 1.0f };
- bool same_font_color = true;
- Color outline_color = Color{ 1.0f, 1.0f, 1.0f };
- bool same_outline_color = true;
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- StringName edited_color;
- StringName edited_font;
- StringName edited_font_size;
-
- // Get override names.
- if (Object::cast_to<RichTextLabel>(edited_control)) {
- edited_color = SNAME("default_color");
- edited_font = SNAME("normal_font");
- edited_font_size = SNAME("normal_font_size");
- } else {
- edited_color = SNAME("font_color");
- edited_font = SNAME("font");
- edited_font_size = SNAME("font_size");
- }
-
- // Get font override.
- Ref<Font> font;
- if (edited_control->has_theme_font_override(edited_font)) {
- font = edited_control->get_theme_font(edited_font);
- }
-
- if (font.is_valid()) {
- if (font->get_data_count() != 1) {
- if (i > 0) {
- same_font = same_font && (custom_font == font);
- }
- custom_font = font;
-
- font_selected = TTR("[Custom Font]");
- same_style = false;
- } else {
- String name = font->get_data(0)->get_font_name();
- String style = font->get_data(0)->get_font_style_name();
- if (fonts.has(name) && fonts[name].has(style)) {
- if (i > 0) {
- same_font = same_font && (name == font_selected);
- same_style = same_style && (style == style_selected);
- }
- font_selected = name;
- style_selected = style;
- } else {
- if (i > 0) {
- same_font = same_font && (custom_font == font);
- }
- custom_font = font;
-
- font_selected = TTR("[Custom Font]");
- same_style = false;
- }
- }
- } else {
- if (i > 0) {
- same_font = same_font && (font_selected == TTR("[Theme Default]"));
- }
-
- font_selected = TTR("[Theme Default]");
- same_style = false;
- }
-
- int current_font_size = edited_control->get_theme_font_size(edited_font_size);
- int current_outline_size = edited_control->get_theme_constant(SNAME("outline_size"));
- Color current_font_color = edited_control->get_theme_color(edited_color);
- Color current_outline_color = edited_control->get_theme_color(SNAME("font_outline_color"));
- if (i > 0) {
- same_font_size = same_font_size && (font_size == current_font_size);
- same_outline_size = same_outline_size && (outline_size == current_outline_size);
- same_font_color = same_font_color && (font_color == current_font_color);
- same_outline_color = same_outline_color && (outline_color == current_outline_color);
- }
-
- font_size = current_font_size;
- outline_size = current_outline_size;
- font_color = current_font_color;
- outline_color = current_outline_color;
- }
- _update_fonts_menu();
- if (same_font) {
- for (int j = 0; j < font_list->get_item_count(); j++) {
- if (font_list->get_item_text(j) == font_selected) {
- font_list->select(j);
- break;
- }
- }
- } else {
- custom_font = Ref<Font>();
- font_list->select(-1);
- }
-
- _update_styles_menu();
- if (same_style) {
- for (int j = 0; j < font_style_list->get_item_count(); j++) {
- if (font_style_list->get_item_text(j) == style_selected) {
- font_style_list->select(j);
- break;
- }
- }
- } else {
- font_style_list->select(-1);
- }
-
- // Get other theme overrides.
- font_size_list->set_block_signals(true);
- if (same_font_size) {
- font_size_list->get_line_edit()->set_text(String::num_uint64(font_size));
- font_size_list->set_value(font_size);
- } else {
- font_size_list->get_line_edit()->set_text("");
- }
- font_size_list->set_block_signals(false);
-
- outline_size_list->set_block_signals(true);
- if (same_outline_size) {
- outline_size_list->get_line_edit()->set_text(String::num_uint64(outline_size));
- outline_size_list->set_value(outline_size);
- } else {
- outline_size_list->get_line_edit()->set_text("");
- }
- outline_size_list->set_block_signals(false);
-
- if (!same_font_color) {
- font_color = Color{ 1.0f, 1.0f, 1.0f };
- }
- font_color_picker->set_pick_color(font_color);
-
- if (!same_outline_color) {
- outline_color = Color{ 1.0f, 1.0f, 1.0f };
- }
- outline_color_picker->set_pick_color(outline_color);
- }
-}
-
-void TextControlEditor::_font_selected(int p_id) {
- _update_styles_menu();
- _set_font();
-}
-
-void TextControlEditor::_font_style_selected(int p_id) {
- _set_font();
-}
-
-void TextControlEditor::_set_font() {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Set Font"));
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- StringName edited_font;
- if (Object::cast_to<RichTextLabel>(edited_control)) {
- edited_font = SNAME("normal_font");
- } else {
- edited_font = SNAME("font");
- }
-
- if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) {
- // Remove font override.
- ur->add_do_method(edited_control, "remove_theme_font_override", edited_font);
- } else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) {
- // Restore "custom_font".
- ur->add_do_method(edited_control, "add_theme_font_override", edited_font, custom_font);
- } else if (font_list->get_selected() >= 0) {
- // Load new font resource using selected name and style.
- String name = font_list->get_item_text(font_list->get_selected());
- String style = font_style_list->get_item_text(font_style_list->get_selected());
- if (style.is_empty()) {
- style = "Default";
- }
- if (fonts.has(name)) {
- Ref<FontData> fd = ResourceLoader::load(fonts[name][style]);
- if (fd.is_valid()) {
- Ref<Font> font;
- font.instantiate();
- font->add_data(fd);
- ur->add_do_method(edited_control, "add_theme_font_override", edited_font, font);
- }
- }
- }
-
- if (edited_control->has_theme_font_override(edited_font)) {
- ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font));
- } else {
- ur->add_undo_method(edited_control, "remove_theme_font_override", edited_font);
- }
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::_font_size_selected(double p_size) {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Set Font Size"));
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- StringName edited_font_size;
- if (Object::cast_to<RichTextLabel>(edited_control)) {
- edited_font_size = SNAME("normal_font_size");
- } else {
- edited_font_size = SNAME("font_size");
- }
-
- ur->add_do_method(edited_control, "add_theme_font_size_override", edited_font_size, p_size);
- if (edited_control->has_theme_font_size_override(edited_font_size)) {
- ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size));
- } else {
- ur->add_undo_method(edited_control, "remove_theme_font_size_override", edited_font_size);
- }
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::_outline_size_selected(double p_size) {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Set Font Outline Size"));
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- ur->add_do_method(edited_control, "add_theme_constant_override", "outline_size", p_size);
- if (edited_control->has_theme_constant_override("outline_size")) {
- ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size")));
- } else {
- ur->add_undo_method(edited_control, "remove_theme_constant_override", "outline_size");
- }
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::_font_color_changed(const Color &p_color) {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Set Font Color"), UndoRedo::MERGE_ENDS);
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- StringName edited_color;
- if (Object::cast_to<RichTextLabel>(edited_control)) {
- edited_color = SNAME("default_color");
- } else {
- edited_color = SNAME("font_color");
- }
-
- ur->add_do_method(edited_control, "add_theme_color_override", edited_color, p_color);
- if (edited_control->has_theme_color_override(edited_color)) {
- ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color));
- } else {
- ur->add_undo_method(edited_control, "remove_theme_color_override", edited_color);
- }
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::_outline_color_changed(const Color &p_color) {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Set Font Outline Color"), UndoRedo::MERGE_ENDS);
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- ur->add_do_method(edited_control, "add_theme_color_override", "font_outline_color", p_color);
- if (edited_control->has_theme_color_override("font_outline_color")) {
- ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color")));
- } else {
- ur->add_undo_method(edited_control, "remove_theme_color_override", "font_outline_color");
- }
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::_clear_formatting() {
- if (edited_controls.is_empty()) {
- return;
- }
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Clear Control Formatting"));
-
- int count = edited_controls.size();
- for (int i = 0; i < count; ++i) {
- Control *edited_control = edited_controls[i];
-
- StringName edited_color;
- StringName edited_font;
- StringName edited_font_size;
-
- // Get override names.
- if (Object::cast_to<RichTextLabel>(edited_control)) {
- edited_color = SNAME("default_color");
- edited_font = SNAME("normal_font");
- edited_font_size = SNAME("normal_font_size");
- } else {
- edited_color = SNAME("font_color");
- edited_font = SNAME("font");
- edited_font_size = SNAME("font_size");
- }
-
- ur->add_do_method(edited_control, "begin_bulk_theme_override");
- ur->add_undo_method(edited_control, "begin_bulk_theme_override");
-
- ur->add_do_method(edited_control, "remove_theme_font_override", edited_font);
- if (edited_control->has_theme_font_override(edited_font)) {
- ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font));
- }
-
- ur->add_do_method(edited_control, "remove_theme_font_size_override", edited_font_size);
- if (edited_control->has_theme_font_size_override(edited_font_size)) {
- ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size));
- }
-
- ur->add_do_method(edited_control, "remove_theme_color_override", edited_color);
- if (edited_control->has_theme_color_override(edited_color)) {
- ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color));
- }
-
- ur->add_do_method(edited_control, "remove_theme_color_override", "font_outline_color");
- if (edited_control->has_theme_color_override("font_outline_color")) {
- ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color")));
- }
-
- ur->add_do_method(edited_control, "remove_theme_constant_override", "outline_size");
- if (edited_control->has_theme_constant_override("outline_size")) {
- ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size")));
- }
-
- ur->add_do_method(edited_control, "end_bulk_theme_override");
- ur->add_undo_method(edited_control, "end_bulk_theme_override");
- }
-
- ur->add_do_method(this, "_update_control");
- ur->add_undo_method(this, "_update_control");
-
- ur->commit_action();
-}
-
-void TextControlEditor::edit(Object *p_object) {
- Control *ctrl = Object::cast_to<Control>(p_object);
- MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object);
-
- edited_controls.clear();
- custom_font = Ref<Font>();
- if (ctrl) {
- edited_controls.append(ctrl);
- _update_control();
- } else if (multi_node && handles(multi_node)) {
- int count = multi_node->get_node_count();
- Node *scene = EditorNode::get_singleton()->get_edited_scene();
-
- for (int i = 0; i < count; ++i) {
- Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i)));
- edited_controls.append(child);
- }
- _update_control();
- }
-}
-
-bool TextControlEditor::handles(Object *p_object) const {
- Control *ctrl = Object::cast_to<Control>(p_object);
- MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object);
-
- if (!ctrl && !multi_node) {
- return false;
- } else if (ctrl) {
- bool valid = false;
- ctrl->get("text", &valid);
- return valid;
- } else {
- bool valid = true;
- int count = multi_node->get_node_count();
- Node *scene = EditorNode::get_singleton()->get_edited_scene();
-
- for (int i = 0; i < count; ++i) {
- bool temp_valid = false;
- Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i)));
- if (child) {
- child->get("text", &temp_valid);
- }
- valid = valid && temp_valid;
-
- if (!valid) {
- break;
- }
- }
-
- return valid;
- }
-}
-
-TextControlEditor::TextControlEditor() {
- add_child(memnew(VSeparator));
-
- font_list = memnew(OptionButton);
- font_list->set_flat(true);
- font_list->set_tooltip(TTR("Font"));
- add_child(font_list);
- font_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_selected));
-
- font_style_list = memnew(OptionButton);
- font_style_list->set_flat(true);
- font_style_list->set_tooltip(TTR("Font style"));
- font_style_list->set_toggle_mode(true);
- add_child(font_style_list);
- font_style_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_style_selected));
-
- font_size_list = memnew(SpinBox);
- font_size_list->set_tooltip(TTR("Font Size"));
- font_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2);
- font_size_list->set_min(6);
- font_size_list->set_step(1);
- font_size_list->set_max(96);
- font_size_list->get_line_edit()->set_flat(true);
- add_child(font_size_list);
- font_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_font_size_selected));
-
- font_color_picker = memnew(ColorPickerButton);
- font_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
- font_color_picker->set_flat(true);
- font_color_picker->set_tooltip(TTR("Text Color"));
- add_child(font_color_picker);
- font_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_font_color_changed));
-
- add_child(memnew(VSeparator));
-
- outline_size_list = memnew(SpinBox);
- outline_size_list->set_tooltip(TTR("Outline Size"));
- outline_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2);
- outline_size_list->set_min(0);
- outline_size_list->set_step(1);
- outline_size_list->set_max(96);
- outline_size_list->get_line_edit()->set_flat(true);
- add_child(outline_size_list);
- outline_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_outline_size_selected));
-
- outline_color_picker = memnew(ColorPickerButton);
- outline_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE);
- outline_color_picker->set_flat(true);
- outline_color_picker->set_tooltip(TTR("Outline Color"));
- add_child(outline_color_picker);
- outline_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_outline_color_changed));
-
- add_child(memnew(VSeparator));
-
- clear_formatting = memnew(Button);
- clear_formatting->set_flat(true);
- clear_formatting->set_tooltip(TTR("Clear Formatting"));
- add_child(clear_formatting);
- clear_formatting->connect("pressed", callable_mp(this, &TextControlEditor::_clear_formatting));
-}
-
-/*************************************************************************/
-
-void TextControlEditorPlugin::edit(Object *p_object) {
- text_ctl_editor->edit(p_object);
-}
-
-bool TextControlEditorPlugin::handles(Object *p_object) const {
- return text_ctl_editor->handles(p_object);
-}
-
-void TextControlEditorPlugin::make_visible(bool p_visible) {
- if (p_visible) {
- text_ctl_editor->show();
- } else {
- text_ctl_editor->hide();
- text_ctl_editor->edit(nullptr);
- }
-}
-
-TextControlEditorPlugin::TextControlEditorPlugin() {
- text_ctl_editor = memnew(TextControlEditor);
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(text_ctl_editor);
-
- text_ctl_editor->hide();
-}
diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h
deleted file mode 100644
index cf069338b6..0000000000
--- a/editor/plugins/text_control_editor_plugin.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************************************/
-/* text_control_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef TEXT_CONTROL_EDITOR_PLUGIN_H
-#define TEXT_CONTROL_EDITOR_PLUGIN_H
-
-#include "canvas_item_editor_plugin.h"
-#include "editor/editor_file_system.h"
-#include "editor/editor_inspector.h"
-#include "editor/editor_plugin.h"
-#include "scene/gui/color_picker.h"
-#include "scene/gui/color_rect.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/popup_menu.h"
-
-/*************************************************************************/
-
-class TextControlEditor : public HBoxContainer {
- GDCLASS(TextControlEditor, HBoxContainer);
-
- enum FontInfoID {
- FONT_INFO_THEME_DEFAULT = 0,
- FONT_INFO_USER_CUSTOM = 1,
- FONT_INFO_ID = 100,
- };
-
- HashMap<String, HashMap<String, String>> fonts;
-
- OptionButton *font_list = nullptr;
- SpinBox *font_size_list = nullptr;
- OptionButton *font_style_list = nullptr;
- ColorPickerButton *font_color_picker = nullptr;
- SpinBox *outline_size_list = nullptr;
- ColorPickerButton *outline_color_picker = nullptr;
- Button *clear_formatting = nullptr;
-
- Vector<Control *> edited_controls;
- Ref<Font> custom_font;
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
- void _find_resources(EditorFileSystemDirectory *p_dir);
- void _reload_fonts(const String &p_path);
-
- void _update_fonts_menu();
- void _update_styles_menu();
- void _update_control();
-
- void _font_selected(int p_id);
- void _font_style_selected(int p_id);
- void _set_font();
-
- void _font_size_selected(double p_size);
- void _outline_size_selected(double p_size);
-
- void _font_color_changed(const Color &p_color);
- void _outline_color_changed(const Color &p_color);
-
- void _clear_formatting();
-
-public:
- void edit(Object *p_object);
- bool handles(Object *p_object) const;
-
- TextControlEditor();
-};
-
-/*************************************************************************/
-
-class TextControlEditorPlugin : public EditorPlugin {
- GDCLASS(TextControlEditorPlugin, EditorPlugin);
-
- TextControlEditor *text_ctl_editor = nullptr;
-
-public:
- virtual String get_name() const override { return "TextControlFontEditor"; }
- bool has_main_screen() const override { return false; }
- virtual void edit(Object *p_object) override;
- virtual bool handles(Object *p_object) const override;
- virtual void make_visible(bool p_visible) override;
-
- TextControlEditorPlugin();
-};
-
-#endif // TEXT_CONTROL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index c7dc61b3a8..b01b90cd08 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -2931,10 +2931,6 @@ void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) {
ur->add_undo_method(*edited_theme, "set_font", p_item_name, edited_type, Ref<Font>());
}
} break;
- case Theme::DATA_TYPE_FONT_SIZE: {
- ur->add_do_method(*edited_theme, "clear_font_size", p_item_name, edited_type);
- ur->add_undo_method(*edited_theme, "set_font_size", p_item_name, edited_type, edited_theme->get_font_size(p_item_name, edited_type));
- } break;
case Theme::DATA_TYPE_ICON: {
ur->add_do_method(*edited_theme, "clear_icon", p_item_name, edited_type);
if (edited_theme->has_icon(p_item_name, edited_type)) {
@@ -3698,7 +3694,7 @@ bool ThemeEditorPlugin::handles(Object *p_node) const {
// If we are editing a theme already and this particular resource happens to belong to it,
// then we just keep editing it, despite not being able to directly handle it.
- // This only goes one layer deep, but if required this can be extended to support, say, FontData inside of Font.
+ // This only goes one layer deep, but if required this can be extended to support, say, Font inside of Font.
bool belongs_to_theme = false;
if (Object::cast_to<Font>(p_node)) {
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index a6e34cf5e0..826631d750 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -126,7 +126,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, theme_cache.font_size);
+ highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, HORIZONTAL_ALIGNMENT_LEFT, -1, 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);
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index e37878ff98..02fe65378d 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -116,12 +116,8 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla
}
}
- Ref<ImageTexture> output_image_texture;
- output_image_texture.instantiate();
- output_image_texture->create_from_image(output_image);
-
merged->set_name(p_atlas_sources[0]->get_name());
- merged->set_texture(output_image_texture);
+ merged->set_texture(ImageTexture::create_from_image(output_image));
merged->set_texture_region_size(new_texture_region_size);
}
}
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 468681c967..1263ee5758 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -218,7 +218,7 @@ void GenericTilePolygonEditor::_base_control_draw() {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
String text = multiple_polygon_mode ? vformat("%d:%d", tinted_polygon_index, tinted_point_index) : vformat("%d", tinted_point_index);
- Size2 text_size = font->get_string_size(text, font_size);
+ Size2 text_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
base_control->draw_string(font, xform.xform(polygons[tinted_polygon_index][tinted_point_index]) - text_size * 0.5, text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
@@ -1116,8 +1116,9 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
}
}
- 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, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ p_canvas_item->draw_string_outline(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
@@ -1727,8 +1728,9 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
} else {
text = "-";
}
- 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, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
}
@@ -1918,8 +1920,9 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
} else {
text = "-";
}
- 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, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
+ p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1));
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color);
}
}
}
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 543304346e..419d0ffcfc 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -121,12 +121,9 @@ void TilesEditorPlugin::_thread() {
pattern_preview_done.wait();
Ref<Image> image = viewport->get_texture()->get_image();
- Ref<ImageTexture> image_texture;
- image_texture.instantiate();
- image_texture->create_from_image(image);
// Find the index for the given pattern. TODO: optimize.
- Variant args[] = { item.pattern, image_texture };
+ Variant args[] = { item.pattern, ImageTexture::create_from_image(image) };
const Variant *args_ptr[] = { &args[0], &args[1] };
Variant r;
Callable::CallError error;
diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp
index 9ed3b72587..654ebf4573 100644
--- a/editor/project_converter_3_to_4.cpp
+++ b/editor/project_converter_3_to_4.cpp
@@ -1253,7 +1253,7 @@ static const char *class_renames[][2] = {
{ "AudioStreamRandomPitch", "AudioStreamRandomizer" },
{ "BakedLightmap", "LightmapGI" },
{ "BakedLightmapData", "LightmapGIData" },
- { "BitmapFont", "Font" },
+ { "BitmapFont", "FontFile" },
{ "BoneAttachment", "BoneAttachment3D" },
{ "BoxShape", "BoxShape3D" },
{ "CPUParticles", "CPUParticles3D" },
@@ -1279,8 +1279,8 @@ static const char *class_renames[][2] = {
{ "CubeMesh", "BoxMesh" },
{ "CylinderShape", "CylinderShape3D" },
{ "DirectionalLight", "DirectionalLight3D" },
- { "DynamicFont", "Font" },
- { "DynamicFontData", "FontData" },
+ { "DynamicFont", "FontFile" },
+ { "DynamicFontData", "FontFile" },
{ "EditorNavigationMeshGenerator", "NavigationMeshGenerator" },
{ "EditorSceneImporter", "EditorSceneFormatImporter" },
{ "EditorSceneImporterFBX", "EditorSceneFormatImporterFBX" },
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 030337a4bc..ac32027219 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -366,16 +366,17 @@ void ProjectExportDialog::_update_feature_list() {
}
custom_feature_display->clear();
+ String text;
bool first = true;
for (const String &E : fset) {
- String f = E;
if (!first) {
- f += ", ";
+ text += ", ";
} else {
first = false;
}
- custom_feature_display->add_text(f);
+ text += E;
}
+ custom_feature_display->add_text(text);
}
void ProjectExportDialog::_custom_features_changed(const String &p_text) {
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index ef91128146..d1aa1ceae6 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1167,9 +1167,7 @@ void ProjectList::load_project_icon(int p_index) {
Error err = img->load(item.icon.replace_first("res://", item.path + "/"));
if (err == OK) {
img->resize(default_icon->get_width(), default_icon->get_height(), Image::INTERPOLATE_LANCZOS);
- Ref<ImageTexture> it = memnew(ImageTexture);
- it->create_from_image(img);
- icon = it;
+ icon = ImageTexture::create_from_image(img);
}
}
if (icon.is_null()) {
@@ -1895,7 +1893,6 @@ void ProjectManager::_notification(int p_what) {
}
if (asset_library) {
real_t size = get_size().x / EDSCALE;
- asset_library->set_columns(size < 1000 ? 1 : 2);
// Adjust names of tabs to fit the new size.
if (size < 650) {
local_projects_hb->set_name(TTR("Local"));
@@ -2798,7 +2795,7 @@ ProjectManager::ProjectManager() {
tabs->add_child(asset_library);
asset_library->connect("install_asset", callable_mp(this, &ProjectManager::_install_project));
} else {
- WARN_PRINT("Asset Library not available, as it requires SSL to work.");
+ print_verbose("Asset Library not available (due to using Web editor, or SSL support disabled).");
}
{
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index d936e821df..9f13a9d520 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -831,11 +831,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
// get default color picker mode from editor settings
int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
- if (default_color_mode == 1) {
- color_picker->set_hsv_mode(true);
- } else if (default_color_mode == 2) {
- color_picker->set_raw_mode(true);
- }
+ color_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
color_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
diff --git a/editor/translations/af.po b/editor/translations/af.po
index 00c05287a1..db28610435 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -413,6 +413,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Aktiveer"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5556,6 +5561,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Alle Seleksie"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18703,6 +18713,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Anim Dupliseer Sleutels"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18711,6 +18726,16 @@ msgstr ""
msgid "Export Format"
msgstr "Anim Verander Transform"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Afhanklikheid Bewerker"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Skrap"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18747,16 +18772,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Afhanklikheid Bewerker"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Skrap"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18994,12 +19009,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19008,17 +19023,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20645,7 +20680,7 @@ msgstr "Zoem In"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21355,6 +21390,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Konstant"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Installeer"
@@ -21363,29 +21403,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Aktiveer"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktiveer"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktiveer"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24563,6 +24608,11 @@ msgstr "Skep Vouer"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Slegs Seleksie"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktiveer"
@@ -24947,16 +24997,17 @@ msgstr "Fokus Pad"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index f449036b53..93bc2971e8 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -64,13 +64,14 @@
# ywmaa <ywmaa.personal@gmail.com>, 2022.
# Awab Najim <dev.djvan@gmail.com>, 2022.
# Abderrahim <abdoudido117@gmail.com>, 2022.
+# Jhon Smith <jhonsmaith3@gmail.com>, 2022.
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: 2022-06-29 10:04+0000\n"
-"Last-Translator: Awab Najim <dev.djvan@gmail.com>\n"
+"PO-Revision-Date: 2022-07-05 07:17+0000\n"
+"Last-Translator: Jhon Smith <jhonsmaith3@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -447,6 +448,11 @@ msgstr "المرجعية الذاتية (Meta)"
msgid "Command"
msgstr "Ù…ÙØªØ§Ø­ Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Ùيزيائي)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5592,6 +5598,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "تنقل ÙÙŠ سجل أزرار الماوس الإضاÙية"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "تحديد الملئ خريطة-الشبكة"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "المظهر"
@@ -9672,7 +9683,7 @@ msgstr "الأيقونة"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "ID"
-msgstr ""
+msgstr "بطاقة تعريÙ"
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -10748,11 +10759,11 @@ msgstr "توقÙ"
#: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp
#: editor/script_editor_debugger.cpp
msgid "Continue"
-msgstr "استمرار"
+msgstr "يكمل"
#: editor/plugins/script_editor_plugin.cpp
msgid "Keep Debugger Open"
-msgstr "إبقاء منÙقتح الأخطاء البرمجية Ù…ÙØªÙˆØ­Ø§Ù‹"
+msgstr "إبقاء المصحح Ù…ÙØªÙˆØ­Ù‹Ø§"
#: editor/plugins/script_editor_plugin.cpp
msgid "Debug with External Editor"
@@ -18844,6 +18855,11 @@ msgid "The package must have at least one '.' separator."
msgstr "يجب أن تتضمن الرزمة على الأقل واحد من الÙواصل '.' ."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "قص العÙقد"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18852,6 +18868,16 @@ msgstr ""
msgid "Export Format"
msgstr "مسار التصدير"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "حجم الخطوط:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "الهدÙ"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18895,16 +18921,6 @@ msgstr "ØªÙØ­Øµ النمذجة السابقة"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "حجم الخطوط:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "الهدÙ"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19164,7 +19180,7 @@ msgstr "يجب ØªÙØ¹ÙŠÙ„ \"Use Custom Build\" لإستخدام Ø§Ù„Ø¥Ø¶Ø§ÙØ§Øª
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" تكون صالحة Ùقط عندما يكون وضع ال \"Xr Mode\"هو \"Oculus "
@@ -19172,7 +19188,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" تكون صالحة Ùقط عندما يكون وضع ال \"Xr Mode\"هو \"Oculus "
"Mobile VR\"."
@@ -19186,22 +19202,43 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"يصبح خيار \"تصدير ABB\" صالحاً Ùقط عندما يتم اختيار \"استعمال تصدير مخصص "
"Custom Build\"."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"يصبح خيار \"تصدير ABB\" صالحاً Ùقط عندما يتم اختيار \"استعمال تصدير مخصص "
"Custom Build\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"إصدار \"حزمة التطوير البرمجية Ø§Ù„Ù…Ø³ØªÙ‡Ø¯ÙØ©\" يجب أن يكون أعلى من أو يساوي إصدار "
"\"Min Sdk\"."
@@ -20874,7 +20911,7 @@ msgstr "تكبير"
msgid "Custom Viewport"
msgstr "ساحة رؤية واحدة"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21655,6 +21692,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "الربط"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
@@ -21663,6 +21705,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "إعدادات متقدمة"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "ØªÙØ¹ÙŠÙ„"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21680,16 +21737,6 @@ msgstr "القلب Ø£Ùقياً"
msgid "Max Speed"
msgstr "السرعة:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "اختر Ø§Ù„Ù…Ø³Ø§ÙØ©:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "ØªÙØ¹ÙŠÙ„"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25122,6 +25169,11 @@ msgstr "مجلد:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "المحدد Ùقط"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "ØªÙØ¹ÙŠÙ„"
@@ -25525,17 +25577,6 @@ msgid "Viewport Path"
msgstr "مسار التصدير"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"لم يتم تعيين Ù…Ù†ÙØ° العرض هذا كهد٠عرض. إذا كنت تنوي عرض محتوياته مباشرة على "
-"الشاشة ، اجعله تابعًا لعنصر تحكم حتى يتمكن من الحصول على الحجم. خلا٠ذلك ، "
-"اجعلها RenderTarget وقم بتعيين نسيجها الداخلي لبعض العقد لعرضها."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25543,6 +25584,15 @@ msgid ""
msgstr "ينبغي أن يكون حجم إطار العرض أكبر من 0 ليتم الإخراج البصري لأي شيء."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/az.po b/editor/translations/az.po
index f8d5d96a7e..3701234f3d 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -407,6 +407,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Siqnalları filtirlə"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5396,6 +5401,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Ölçmə seçimi"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18002,6 +18012,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Funksiyalar:"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18010,6 +18025,14 @@ msgstr ""
msgid "Export Format"
msgstr "3D Transformasya izi"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18046,14 +18069,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18279,12 +18294,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18293,17 +18308,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19848,7 +19883,7 @@ msgstr "Yaxınlaşdır"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20529,6 +20564,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
msgid "Path Desired Distance"
msgstr "Quraşdır"
@@ -20538,29 +20577,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Qabaqcıl"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Siqnalları filtirlə"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Siqnalları filtirlə"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23636,6 +23680,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Yalnız Seçim"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Siqnalları filtirlə"
@@ -24002,16 +24051,17 @@ msgstr "Yol"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index aa0fac6038..105aad00db 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -431,6 +431,11 @@ msgstr "Мета"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Включване"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5480,6 +5485,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "ÐаÑтройки"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18343,6 +18353,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Пакетът трÑбва да има поне един разделител „.“ (точка)."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ПерÑонализиран обект"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18351,6 +18366,16 @@ msgstr ""
msgid "Export Format"
msgstr "Път за изнаÑÑне"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Размер на контура:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Принудително изпращане"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18392,16 +18417,6 @@ msgstr "Предишен раздел"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Размер на контура:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Принудително изпращане"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18647,12 +18662,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18662,22 +18677,45 @@ msgstr ""
"ÑобÑтвена компилациÑ“."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"„Мин. верÑÐ¸Ñ Ð½Ð° SDK“ може да Ñе Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ Ñамо когато „Използване на ÑобÑтвена "
"компилациÑ“ е включено."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"„Целева верÑÐ¸Ñ Ð½Ð° SDK“ може да Ñе Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ Ñамо когато „Използване на "
"ÑобÑтвена компилациÑ“ е включено."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"„Целева верÑÐ¸Ñ Ð½Ð° SDK“ трÑбва да бъде по-голÑма или равна на „Мин. верÑÐ¸Ñ Ð½Ð° "
"SDK“."
@@ -20333,7 +20371,7 @@ msgstr "Приближаване"
msgid "Custom Viewport"
msgstr "1 прозорец за изглед"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21081,6 +21119,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ОтÑтъп"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Изберете главна Ñцена"
@@ -21089,6 +21132,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Включване"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Включване"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21106,15 +21163,6 @@ msgstr "Хоризонтала:"
msgid "Max Speed"
msgstr "СкороÑÑ‚:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr ""
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Включване"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24391,6 +24439,11 @@ msgstr "Папка:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Само избраното"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Включване"
@@ -24788,16 +24841,17 @@ msgstr "Път за изнаÑÑне"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index b3c338168c..0e99518ac1 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -421,6 +421,11 @@ msgstr ""
msgid "Command"
msgstr "সমà§à¦ªà§à¦°à¦¦à¦¾à§Ÿ"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "সà§à¦¥à¦¿à¦°/বদà§à¦§ ফà§à¦°à§‡à¦® %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5807,6 +5812,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "নিরà§à¦¬à¦¾à¦šà¦¿à¦¤ সমূহ অপসারণ করà§à¦¨"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19778,6 +19788,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "নোড-সমূহ করà§à¦¤à¦¨/কাট করà§à¦¨"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19786,6 +19801,16 @@ msgstr ""
msgid "Export Format"
msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿà§‡à¦° পà§à¦°à¦¿à¦¸à§‡à¦Ÿ:"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "পà§à¦°à¦¾à¦¨à§à¦¤à¦°à§‡à¦–ার আকার:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "টারà§à¦—েট"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19827,16 +19852,6 @@ msgstr "পূরà§à¦¬à¦¬à¦°à§à¦¤à§€ ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸ পরà
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "পà§à¦°à¦¾à¦¨à§à¦¤à¦°à§‡à¦–ার আকার:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "টারà§à¦—েট"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -20083,12 +20098,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -20097,17 +20112,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21776,7 +21811,7 @@ msgstr "সমà§à¦ªà§à¦°à¦¸à¦¾à¦°à¦¿à¦¤ করà§à¦¨ (জà§à¦®à§ ইন)"
msgid "Custom Viewport"
msgstr "১ টি Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -22535,6 +22570,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "যথেচà§à¦› ঘূরà§à¦£à¦¾à§Ÿà¦¨:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:"
@@ -22543,6 +22583,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "অà§à¦¯à¦¾à¦¨à¦¿à¦®à§‡à¦¶à¦¨à§‡à¦° সিদà§à¦§à¦¾à¦¨à§à¦¤à¦¸à¦®à§‚হ"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "সকà§à¦°à¦¿à¦¯à¦¼ করà§à¦¨"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -22559,16 +22614,6 @@ msgstr ""
msgid "Max Speed"
msgstr "গতি (FPS):"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "ইনà§à¦¸à¦Ÿà§à¦¯à¦¾à¦¨à§à¦¸:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "সকà§à¦°à¦¿à¦¯à¦¼ করà§à¦¨"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25926,6 +25971,11 @@ msgstr "লাইন-ঠযান"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "শà§à¦§à§à¦®à¦¾à¦¤à§à¦° নিরà§à¦¬à¦¾à¦šà¦¿à¦¤à¦¸à¦®à§‚হ"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "সকà§à¦°à¦¿à¦¯à¦¼ করà§à¦¨"
@@ -26327,20 +26377,17 @@ msgstr "à¦à¦•à§à¦¸à¦ªà§‹à¦°à§à¦Ÿà§‡à¦° পà§à¦°à¦¿à¦¸à§‡à¦Ÿ:"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"à¦à¦‡ viewport টি render target হিসেবে নিরà§à¦§à¦¾à¦°à¦¨ করা নেই। আপনি যদি à¦à¦° বসà§à¦¤à§-সামগà§à¦°à§€ "
-"সরাসরি পরà§à¦¦à¦¾à§Ÿ দেখাতে চান, à¦à¦Ÿà¦¿à¦•ে যেকোনো Control à¦à¦° অংশভূত করà§à¦¨ যেনো à¦à¦Ÿà¦¿ à¦à¦•টি "
-"আকার ধারণ করতে পারে। অনà§à¦¯à¦¥à¦¾à§Ÿ, à¦à¦Ÿà¦¿à¦•ে à¦à¦•টি RenderTarget করà§à¦¨ à¦à¦¬à¦‚ à¦à¦° অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ "
-"দৃশà§à¦¯à¦¾à¦¬à¦²à¦¿à¦•ে (texture) দৃশà§à¦¯à¦®à¦¾à¦¨ করতে কোনো নোডে হসà§à¦¤à¦¾à¦¨à§à¦¤à¦° করà§à¦¨à¥¤"
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/br.po b/editor/translations/br.po
index c5d979fe2f..101a0f7581 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -397,6 +397,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Aktivañ ar Roudenn"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5305,6 +5310,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17814,6 +17823,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Fonksionoù :"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17822,6 +17836,14 @@ msgstr ""
msgid "Export Format"
msgstr "Roudenn Treuzfurmadur 3D"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17858,14 +17880,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18088,12 +18102,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18102,17 +18116,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19639,7 +19673,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20311,6 +20345,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20319,29 +20357,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Aktivañ ar Roudenn"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktivañ ar Roudenn"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktivañ ar Roudenn"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23379,6 +23422,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Aktivañ ar Roudenn"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktivañ ar Roudenn"
@@ -23737,16 +23785,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 1e1ec84901..c9726505d3 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -409,6 +409,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Comunitat"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fotograma de Física %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5616,6 +5621,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Elimina la Selecció del GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19209,6 +19219,11 @@ msgid "The package must have at least one '.' separator."
msgstr "El paquet ha de tenir com a mínim un separador '. '."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Talla els Nodes"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19217,6 +19232,16 @@ msgstr ""
msgid "Export Format"
msgstr "Camí d'exportació"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Mida del Contorn:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Objectiu"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -19259,16 +19284,6 @@ msgstr "Inspecciona la Instància anterior"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Mida del Contorn:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Objectiu"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19523,12 +19538,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19537,17 +19552,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21234,7 +21269,7 @@ msgstr "Apropa"
msgid "Custom Viewport"
msgstr "1 Vista"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -22001,6 +22036,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Vinculació"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Trieu la distància:"
@@ -22009,6 +22049,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Trieu la distància:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avançat"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -22026,16 +22081,6 @@ msgstr "Volteja Horitzontalment"
msgid "Max Speed"
msgstr "Velocitat (FPS):"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Trieu la distància:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activar"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25451,6 +25496,11 @@ msgstr "Directori:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Selecció Només"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activar"
@@ -25858,20 +25908,17 @@ msgstr "Camí d'exportació"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"La Vista (Viewport) no és la Destinació de Renderització (render target). "
-"Per mostrar-ne el contingut, especifiqueu-la com a filla d'un Control de "
-"forma per tal d'obtenir-ne la mida. Altrament, establiu-la com a Destinació "
-"de Renderització i assigneu-ne la textura interna a algun node."
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index ade3299077..0c0b8b63ca 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -452,6 +452,11 @@ msgstr ""
msgid "Command"
msgstr "Komunita"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fyzická Klávesa"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5667,6 +5672,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Vyplnit výběr"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18952,6 +18962,11 @@ msgid "The package must have at least one '.' separator."
msgstr "BalíÄek musí mít alespoň jeden '.' oddÄ›lovaÄ."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Vyjmout uzly"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18960,6 +18975,16 @@ msgstr ""
msgid "Export Format"
msgstr "Exportovat cestu"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Velikost obrysu:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Cíl"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -19002,16 +19027,6 @@ msgstr "Zkontrolovat předchozí instanci"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Velikost obrysu:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Cíl"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19261,7 +19276,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" je platné pouze v případě, že \"Režim Xr\" má hodnotu "
@@ -19269,7 +19284,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" je platné pouze v případě, že \"Režim Xr\" má hodnotu "
"\"Oculus Mobile VR\"."
@@ -19283,22 +19298,42 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Export AAB\" je validní pouze v případě, že je povolena možnost \"Použít "
"vlastní sestavu\"."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Export AAB\" je validní pouze v případě, že je povolena možnost \"Použít "
"vlastní sestavu\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20968,7 +21003,7 @@ msgstr "Zvětšit"
msgid "Custom Viewport"
msgstr "1 výřez"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21736,6 +21771,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Vazba"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Vybrat vzdálenost:"
@@ -21744,6 +21784,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Vybrat vzdálenost:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "PokroÄilé"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Povolit"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21761,16 +21816,6 @@ msgstr "Převrátit horizontálně"
msgid "Max Speed"
msgstr "Rychlost:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Vybrat vzdálenost:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Povolit"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25180,6 +25225,11 @@ msgstr "Složka:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Pouze výběr"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Povolit"
@@ -25585,18 +25635,6 @@ msgid "Viewport Path"
msgstr "Exportovat cestu"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Tento viewport není nastaven jako render target. Pokud chcete jeho obsah "
-"zobrazit přímo na obrazovku, musíte ho nastavit jako dítě uzlu Control, aby "
-"mohl získat velikost. Jinak ho nastavte jako render target a pÅ™iÅ™aÄte jeho "
-"vnitřní texturu nějakému uzlu k zobrazení."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25605,6 +25643,15 @@ msgstr ""
"Velikost pohledu musí být větší než 0, aby bylo možné cokoliv renderovat."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 168f98fbf1..3b19f24ec8 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -423,6 +423,11 @@ msgstr ""
msgid "Command"
msgstr "Fællesskab"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fysik Frame %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5720,6 +5725,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Slet Markerede"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19157,6 +19167,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Indsæt Node"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19165,6 +19180,16 @@ msgstr ""
msgid "Export Format"
msgstr "Eksporter Projekt"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Skrifttype Størrelse:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Tidsskala Node"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19203,16 +19228,6 @@ msgstr "Forrige fane"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Skrifttype Størrelse:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Tidsskala Node"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19458,12 +19473,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19472,17 +19487,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21142,7 +21177,7 @@ msgstr "Zoom Ind"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21875,6 +21910,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Konstant"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Vælg en Main Scene"
@@ -21883,29 +21923,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Balanceret"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktivér"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktivér"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25177,6 +25222,11 @@ msgstr "Opret Mappe"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Kun Valgte"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktivér"
@@ -25572,20 +25622,17 @@ msgstr "Eksporter Projekt"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"Denne viewport er ikke angivet som render target. Hvis du har tænkt dig for "
-"at vise dens indhold direkte til skærmen, gør det til et barn af Control, så "
-"den kan opnå en størrelse. Ellers gør den til en RenderTarget og tildel dens "
-"indre textur til en node så den kan vises."
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 61cfb48184..f0c79cda0f 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -87,7 +87,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: 2022-06-26 16:16+0000\n"
+"PO-Revision-Date: 2022-06-30 16:42+0000\n"
"Last-Translator: So Wieso <sowieso@dukun.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
@@ -465,6 +465,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Befehl"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (physisch)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5555,6 +5560,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Extramaustasten blättern durch Verlauf"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap-Auswahl"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aussehen"
@@ -18439,6 +18449,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Das Paket muss mindestens einen Punkt-Unterteiler ‚.‘ haben."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Einen Build verwenden"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Einen Build verwenden"
@@ -18446,6 +18461,14 @@ msgstr "Einen Build verwenden"
msgid "Export Format"
msgstr "Exportformat"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "Min SDK"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "Ziel SDK"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr "Architekturen"
@@ -18482,14 +18505,6 @@ msgstr "Vorherige Installation löschen"
msgid "Code"
msgstr "Code"
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "Min SDK"
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr "Ziel SDK"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr "Packet"
@@ -18728,15 +18743,17 @@ msgstr ""
"„Use Custom Build“ muss aktiviert werden um die Plugins nutzen zu können."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"„Hand Tracking“ ist nur gültig wenn „Xr Mode“ als „Occulus Mobile VrApi“ "
"oder „OpenXR“ gesetzt wurde."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"„Passthrough“ ist nur gültig wenn „Xr Mode“ als „OpenXR“ gesetzt wurde."
@@ -18745,22 +18762,45 @@ msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
msgstr "„Export AAB“ ist nur gültig wenn „Use Custom Build“ aktiviert ist."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Das „Min Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert "
"ist."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Das „Target Sdk“ zu ändern ist nur möglich wenn „Use Custom Build“ aktiviert "
"ist."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"Die Version des „Target Sdk“ muss größer gleich der des „Min Sdk“ sein."
@@ -20354,7 +20394,7 @@ msgstr "Vergrößerung"
msgid "Custom Viewport"
msgstr "Eigenes Ansichtsfenster"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -21048,17 +21088,37 @@ msgid ""
"will be removed in a future version. Use 'Navigation2DServer.map_get_path()' "
"instead."
msgstr ""
+"‚Navigation2D‘ und ‚Navigation2D.get_simple_path()‘ sind veraltet und werden "
+"in einer zukünftigen Version entfernt. Als Ersatz ist ‚Navigation2DServer."
+"map_get_path()‘ zu verwenden."
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Zuordnung"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
-msgstr "Gewünschte Zieldistanz"
+msgstr "Gewünschte Pfaddistanz"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Target Desired Distance"
msgstr "Gewünschte Zieldistanz"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "Max Pfad-Distanz"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Erweitert"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance Enabled"
+msgstr "Vermeiden aktiviert"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr "Nachbardistanz"
@@ -21074,14 +21134,6 @@ msgstr "Zeithorizont"
msgid "Max Speed"
msgstr "Max Geschw"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr "Max Pfad-Distanz"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
-msgstr "Vermeiden aktiviert"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -22217,6 +22269,9 @@ msgid ""
"be removed in a future version. Use 'NavigationServer.map_get_path()' "
"instead."
msgstr ""
+"‚Navigation‘ und ‚Navigation.get_simple_path()‘ sind veraltet und werden in "
+"einer zukünftigen Version entfernt. Als Ersatz ist ‚NavigationServer."
+"map_get_path()‘ zu verwenden."
#: scene/3d/navigation.cpp scene/resources/curve.cpp
msgid "Up Vector"
@@ -24158,6 +24213,11 @@ msgid "Fold Gutter"
msgstr "Einklappenspalte"
#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Textauswahl möglich"
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr "Verstecken aktiviert"
@@ -24518,19 +24578,6 @@ msgstr "Ansichtsfensterpfad"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Dieser Viewport ist nicht als Render-Ziel eingestellt. Soll sein Inhalt "
-"direkt auf dem Bildschirm angezeigt werden, muss er als Unterobjekt eines "
-"Controls eingehängt werden um dessen Größe zu erben. Andernfalls sollte die "
-"Eigenschaft ‚Render Target‘ des Viewports aktiviert und seine Textur "
-"irgendeinem Node zum Anzeigen zugewiesen werden."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -24538,6 +24585,15 @@ msgstr ""
"betragen um überhaupt irgendetwas rendern zu können."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr "ARVR"
@@ -26045,14 +26101,12 @@ msgid "Walkable Low Height Spans"
msgstr "Ablaufbare Abstände niedriger Höhe"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Baking AABB"
-msgstr "Erzeuge AABB"
+msgstr "Backe AABB"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Baking AABB Offset"
-msgstr "Grundversatz"
+msgstr "Backe AABB-Versatz"
#: scene/resources/occluder_shape.cpp
msgid "Spheres"
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 2682db8c4b..5d2d5f1cbc 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -380,6 +380,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5244,6 +5248,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17666,6 +17674,10 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+msgid "Custom Build"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17673,6 +17685,14 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17709,14 +17729,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -17934,12 +17946,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -17948,17 +17960,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19460,7 +19492,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20122,6 +20154,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20130,27 +20166,31 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
+msgid "Avoidance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+msgid "Avoidance Enabled"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
+msgid "Time Horizon"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Max Speed"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp
@@ -23074,6 +23114,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23425,16 +23469,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/el.po b/editor/translations/el.po
index 21f118d442..a061cc5a59 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -411,6 +411,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Φυσικό)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5649,6 +5654,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Γέμισμα Επιλογής"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19116,6 +19126,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Το πακέτο Ï€Ïέπει να έχει τουλάχιστον έναν '.' διαχωÏιστή."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Αποκοπή κόμβων"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19124,6 +19139,16 @@ msgstr ""
msgid "Export Format"
msgstr "ΔιαδÏομή Εξαγωγής"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Μέγεθος πεÏιγÏάμματος:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Στόχος"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -19166,16 +19191,6 @@ msgstr "ΕπιθεώÏηση του Ï€ÏοηγοÏμενου στιγμιοτÏÏ
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Μέγεθος πεÏιγÏάμματος:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Στόχος"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19437,7 +19452,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"Το «Hand Tracking» είναι έγκυÏο μόνο όταν το «Xr Mode» είναι «Oculus Mobile "
@@ -19445,7 +19460,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"Το «Hand Tracking» είναι έγκυÏο μόνο όταν το «Xr Mode» είναι «Oculus Mobile "
"VR»."
@@ -19456,17 +19471,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21143,7 +21178,7 @@ msgstr "Μεγέθυνση"
msgid "Custom Viewport"
msgstr "1 Οπτική γωνία"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21914,6 +21949,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Δεσμός"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Επιλογή απόστασης:"
@@ -21922,6 +21962,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Επιλογή απόστασης:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Για Ï€ÏοχωÏημένους"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "ΕνεÏγοποίηση"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21939,16 +21994,6 @@ msgstr "ΑναστÏοφή ΟÏιζόντια"
msgid "Max Speed"
msgstr "ΤαχÏτητα:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Επιλογή απόστασης:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "ΕνεÏγοποίηση"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25376,6 +25421,11 @@ msgstr "Φάκελος:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Μόνο στην επιλογή"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "ΕνεÏγοποίηση"
@@ -25781,18 +25831,6 @@ msgid "Viewport Path"
msgstr "ΔιαδÏομή Εξαγωγής"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Το Viewport δεν έχει οÏισθεί ως στόχος απόδοσης. Αν σκοπεÏετε να δείχνει τα "
-"πεÏιεχόμενα του, κάντε το να κληÏονομεί ένα Control, ώστε να αποκτήσει "
-"μέγεθος. Αλλιώς, κάντε το ένα RenderTarget και οÏίστε το internal texture σε "
-"έναν κόμβο για απεικόνιση."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25802,6 +25840,15 @@ msgstr ""
"απόδοση."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/en_Shaw.po b/editor/translations/en_Shaw.po
index bf2aa9d387..1f648844a2 100644
--- a/editor/translations/en_Shaw.po
+++ b/editor/translations/en_Shaw.po
@@ -391,6 +391,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5271,6 +5276,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17739,6 +17748,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ð‘“ð‘³ð‘™ð‘’ð‘–ð‘©ð‘¯ð‘Ÿ:"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17747,6 +17761,14 @@ msgstr ""
msgid "Export Format"
msgstr "3-ð‘› ð‘‘ð‘®ð‘¨ð‘¯ð‘•ð‘“ð‘¹ð‘¥ ð‘‘ð‘®ð‘¨ð‘’"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17783,14 +17805,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18012,12 +18026,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18026,17 +18040,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19556,7 +19590,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20224,6 +20258,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20232,29 +20270,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23269,6 +23312,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "ð‘‘ð‘ªð‘œð‘©ð‘¤ ð‘‘ð‘®ð‘¨ð‘’ ð‘¦ð‘¯ð‘±ð‘šð‘©ð‘¤ð‘›"
@@ -23626,16 +23674,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index 27aeb13ce0..2eef4fc0d0 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -431,6 +431,11 @@ msgstr ""
msgid "Command"
msgstr "Komunumo"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fiziko-kadro %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5642,6 +5647,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Enkadrigi elekton"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18811,6 +18821,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Eltondi nodo(j)n"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18819,6 +18834,16 @@ msgstr ""
msgid "Export Format"
msgstr "Formo"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Grando de konturo:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Celo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18858,16 +18883,6 @@ msgstr "Inspekti antaÅ­an ekzemplon"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Grando de konturo:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Celo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19113,12 +19128,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19127,17 +19142,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20786,7 +20821,7 @@ msgstr "Zomi"
msgid "Custom Viewport"
msgstr "Montri vidujon"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21513,6 +21548,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Alglui animacion"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Elektu ĉefan scenon"
@@ -21521,29 +21561,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Altnivela"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Åœaltita"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Åœaltita"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24822,6 +24867,11 @@ msgstr "Dosierujo:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Nur Elektaro"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Åœaltita"
@@ -25224,16 +25274,17 @@ msgstr "Fokusi al dosierindiko"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 41b1e32779..febff41060 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -466,6 +466,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Física)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5561,6 +5566,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Botones Extra del Ratón Navegar por el Historial"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Seleccionar GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Apariencia"
@@ -18697,6 +18707,11 @@ msgid "The package must have at least one '.' separator."
msgstr "El paquete debe tener al menos un '.' como separador."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "CustomNode"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18705,6 +18720,15 @@ msgstr ""
msgid "Export Format"
msgstr "Ruta de Exportación"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "SDK Mínimo"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Objetivo de FPS"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18748,15 +18772,6 @@ msgstr "Inspeccionar Instancia Anterior"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "SDK Mínimo"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Objetivo de FPS"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19013,15 +19028,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "\"Use Custom Build\" debe estar activado para usar los plugins."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" solo es válido cuando \"Xr Mode\" es \"Oculus Mobile "
"VrApi\" u \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Passthrough\" solo es válido cuando \"Xr Mode\" es \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
@@ -19030,22 +19047,45 @@ msgstr ""
"\"Export AAB\" sólo es válido cuando \"Use Custom Build\" está activado."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Cambiar el \"Min Sdk\" solo es válido cuando \"Use Custom Build\" está "
"activado."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Cambiar el \"Target Sdk\" solo es válido cuando \"Use Custom Build\" está "
"activado."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"La versión de \"Target Sdk\" debe ser mayor o igual que la versión de \"Min "
"Sdk\"."
@@ -20755,7 +20795,7 @@ msgstr "Acercar Zoom"
msgid "Custom Viewport"
msgstr "1 Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21521,6 +21561,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Vinculación"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Distancia de la Ruta U"
@@ -21529,6 +21574,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "Distancia Máxima de Ruta"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avanzado"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21545,15 +21604,6 @@ msgstr "Voltear Horizontalmente"
msgid "Max Speed"
msgstr "Velocidad Máxima"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr "Distancia Máxima de Ruta"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activar"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -24941,6 +24991,11 @@ msgstr "Plegar Gutter"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Sólo selección"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activar"
@@ -25342,19 +25397,6 @@ msgstr "Ruta de Exportación"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Esta ventanilla no está configurada como destino de representación. Si "
-"quiere que su contenido se muestre directamente en la pantalla, hágalo un "
-"elemento secundario de un control para que pueda recibir dimensiones. O "
-"bien, conviértalo en un RenderTarget y asigne su textura interna a algún "
-"nodo para que se muestre."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25362,6 +25404,15 @@ msgstr ""
"dimensiones para renderizar cualquier cosa."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index aa0a7c6258..eeea3a9922 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -413,6 +413,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Comunidad"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Física)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5630,6 +5635,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Selección de GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18901,6 +18911,11 @@ msgid "The package must have at least one '.' separator."
msgstr "El paquete debe tener al menos un '.' como separador."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "CustomNode"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18909,6 +18924,16 @@ msgstr ""
msgid "Export Format"
msgstr "Ruta de Exportación"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Tamaño de Outline:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Objetivo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18952,16 +18977,6 @@ msgstr "Inspeccionar Instancia Previa"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Tamaño de Outline:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Objetivo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19213,15 +19228,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "\"Use Custom Build\" debe estar activado para usar los plugins."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" sólo es válido cuando \"Xr Mode\" es \"Oculus Mobile "
"VrApi\" o \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Passthrough\" sólo es válido cuando \"Xr Mode\" es \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
@@ -19230,22 +19247,45 @@ msgstr ""
"\"Export AAB\" sólo es válido cuando \"Use Custom Build\" está activado."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Cambiar el \"Min Sdk\" sólo es válido cuando \"Use Custom Build\" está "
"activado."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Cambiar el \"Target Sdk\" sólo es válido cuando \"Use Custom Build\" está "
"activado."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"La versión de \"Target Sdk\" debe ser mayor o igual a la versión de \"Min "
"Sdk\"."
@@ -20984,7 +21024,7 @@ msgstr "Zoom In"
msgid "Custom Viewport"
msgstr "1 Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21762,6 +21802,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Binding"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Elegir Instancia:"
@@ -21770,6 +21815,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Elegir Instancia:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avanzado"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21786,16 +21846,6 @@ msgstr "Espejar Horizontalmente"
msgid "Max Speed"
msgstr "Velocidad Máxima"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Elegir Instancia:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activar"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25190,6 +25240,11 @@ msgstr "Carpeta:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Solo Selección"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activar"
@@ -25602,18 +25657,6 @@ msgstr "Ruta de Exportación"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Este viewport no está seteado como render target. Si tienes intención de que "
-"muestre contenidos directo a la pantalla, haz un hijo de un Control para que "
-"pueda obtener un tamaño. Alternativamente, haz un RenderTarget y asigna su "
-"textura interna a algún otro nodo para mostrar."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25621,6 +25664,15 @@ msgstr ""
"dimensiones para renderizar cualquier cosa."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/et.po b/editor/translations/et.po
index f90543b559..b7ed666bb0 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -417,6 +417,11 @@ msgstr ""
msgid "Command"
msgstr "Kogukond"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Luba"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5473,6 +5478,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Kopeeri valik"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18297,6 +18307,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Kustuta sõlm(ed)"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18305,6 +18320,16 @@ msgstr ""
msgid "Export Format"
msgstr "Formaat"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Suurus: "
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Ressursi tee"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18343,16 +18368,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Suurus: "
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Ressursi tee"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18591,12 +18606,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18605,17 +18620,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20238,7 +20273,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr "1 vaateaken"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20951,6 +20986,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Kombinatsioon"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Paigalda"
@@ -20959,29 +20999,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Täpsem"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Luba"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Luba"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24170,6 +24215,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Vali see kaust"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Luba"
@@ -24556,14 +24606,6 @@ msgid "Viewport Path"
msgstr "1 vaateaken"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -24571,6 +24613,15 @@ msgid ""
msgstr "Vaateakne suurus peab olema suurem kui 0, et kuvada."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index 9ffd16f336..ff9601ad57 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -394,6 +394,11 @@ msgstr ""
msgid "Command"
msgstr "Komunitatea"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Gaitu atxikitzea"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5380,6 +5385,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18122,6 +18131,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Kendu elementu guztiak"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18130,6 +18144,15 @@ msgstr ""
msgid "Export Format"
msgstr "Esportatu"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Blend4 nodoa"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18167,15 +18190,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Blend4 nodoa"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18413,12 +18427,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18427,17 +18441,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20032,7 +20066,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20729,6 +20763,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Itsatsi animazioa"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Instalatu"
@@ -20737,29 +20776,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Gaitu atxikitzea"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Gaitu atxikitzea"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Gaitu atxikitzea"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23887,6 +23931,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Hautatu karpeta hau"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Gaitu atxikitzea"
@@ -24266,16 +24315,17 @@ msgstr "Kopiatu bidea"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 0b7bd8cdb1..ae8a37388a 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -441,6 +441,11 @@ msgstr ""
msgid "Command"
msgstr "جامعه"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "روشن"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5535,6 +5540,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "انتخاب شده را حذ٠کن"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19006,6 +19016,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ساختن گره"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19014,6 +19029,16 @@ msgstr ""
msgid "Export Format"
msgstr "صدور پروژه"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "باز کردن و اجرای یک اسکریپت"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "گره تغییر والد"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19052,16 +19077,6 @@ msgstr "زبانه قبلی"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "باز کردن و اجرای یک اسکریپت"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "گره تغییر والد"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19306,12 +19321,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19320,17 +19335,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20980,7 +21015,7 @@ msgstr "بزرگنمایی"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21714,6 +21749,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ثابت"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "نصب کردن"
@@ -21722,29 +21762,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Ù¾ÛŒØ´Ø±ÙØªÙ‡"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "روشن"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "روشن"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25012,6 +25057,11 @@ msgstr "ساختن پوشه"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "تنها در قسمت انتخاب شده"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "روشن"
@@ -25408,20 +25458,17 @@ msgstr "صدور پروژه"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"این viewport به صورت render target تنظیم نیست. اگر قصد دارید که محتویاتش را "
-"به صورت مستقیم در ØµÙØ­Ù‡â€ŒÙ†Ù…ایش نمایش دهد، آن را یک ÙØ±Ø²Ù†Ø¯ یک Control قرار دهید "
-"تا بتواند یک اندازه بگیرد. در غیر اینصورت، آن را یک RenderTarget قرار دهید و "
-"Ø¨Ø§ÙØª داخلی آن را برای نمایش به تعدادی گره تخصیص دهید."
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 24d8fd66ab..7613bdfcce 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -437,6 +437,11 @@ msgstr ""
msgid "Command"
msgstr "Yhteisö"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (fyysinen)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5662,6 +5667,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Ruudukon valinta"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18902,6 +18912,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Paketilla on oltava ainakin yksi '.' erotinmerkki."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Mukautettu solmu"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18910,6 +18925,16 @@ msgstr ""
msgid "Export Format"
msgstr "Vientipolku"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Ääriviivojen koko:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Kohde"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18953,16 +18978,6 @@ msgstr "Tarkastele edellistä ilmentymää"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Ääriviivojen koko:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Kohde"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19216,15 +19231,17 @@ msgstr ""
"käyttää."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" on käyttökelpoinen ainoastaan kun \"Xr Mode\" asetuksen "
"arvo on \"Oculus Mobile VrAPI\" tai \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Passthrough\" on käyttökelpoinen ainoastaan kun \"Xr Mode\" asetuksen arvo "
"on \"OpenXR\"."
@@ -19236,22 +19253,45 @@ msgstr ""
"päällä."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Min Sdk\" vaihtaminen on mahdollista vain, kun \"Use Custom Build\" asetus "
"on päällä."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Target Sdk\" vaihtaminen on mahdollista vain, kun \"Use Custom Build\" "
"asetus on päällä."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"\"Target Sdk\" versionumeron on oltava suurempi tai yhtä suuri kuin \"Min "
"Sdk\" versionumeron."
@@ -20991,7 +21031,7 @@ msgstr "Lähennä"
msgid "Custom Viewport"
msgstr "1 näyttöruutu"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21766,6 +21806,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Sidonta"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Poimintaetäisyys:"
@@ -21774,6 +21819,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Poimintaetäisyys:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Edistyneet"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Ota käyttöön"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21791,16 +21851,6 @@ msgstr "Käännä vaakasuorasti"
msgid "Max Speed"
msgstr "Nopeus:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Poimintaetäisyys:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Ota käyttöön"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -25260,6 +25310,11 @@ msgstr "Kansio:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Pelkkä valinta"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Ota käyttöön"
@@ -25672,18 +25727,6 @@ msgstr "Vientipolku"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Tätä näyttöikkunaa ei ole asetettu renderöitäväksi. Jos haluat sen näyttävän "
-"sisältöä suoraan näytölle, tee sitä Control solmun alisolmu, jotta se voi "
-"saada koon. Muutoin tee siitä RenderTarget ja aseta sen sisäinen tekstuuri "
-"johonkin solmuun näkyväksi."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25691,6 +25734,15 @@ msgstr ""
"kummassakin suunnassa, jotta mitään renderöidään."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index 822a23a9b9..24a5742ef6 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -392,6 +392,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Pisika"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5297,6 +5302,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17868,6 +17877,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Ilipat Ang Mga Bezier Points"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17876,6 +17890,14 @@ msgstr ""
msgid "Export Format"
msgstr "3D Transform Track"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17912,14 +17934,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18143,12 +18157,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18157,17 +18171,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19706,7 +19740,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20383,6 +20417,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20391,29 +20429,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Binuksan ang V-Sync"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Binuksan ang V-Sync"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Binuksan ang V-Sync"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23426,6 +23469,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23786,16 +23833,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index 5711d32f52..8822d35687 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -32,7 +32,7 @@
# Przemyslaw Gasinski <gasinski.przemek@protonmail.ch>, 2017.
# rafeu <duchainer@gmail.com>, 2016-2017.
# rawida <rawida@tempinbox.com>, 2018.
-# Rémi Verschelde <rverschelde@gmail.com>, 2016-2017.
+# Rémi Verschelde <akien@godotengine.org>, 2016-2022.
# Robin Arys <robinarys@hotmail.com>, 2017.
# Roger BR <drai_kin@hotmail.com>, 2016.
# salty64 <cedric.arrabie@univ-pau.fr>, 2018, 2020, 2021.
@@ -49,7 +49,6 @@
# 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, 2021.
# Rémi Bintein <reminus5@hotmail.fr>, 2018, 2019.
# Sylvain Corsini <sylvain.corsini@gmail.com>, 2018.
# Caye Pierre <pierrecaye@laposte.net>, 2019.
@@ -66,7 +65,7 @@
# Fabrice <fabricecipolla@gmail.com>, 2019.
# Romain Paquet <titou.paquet@gmail.com>, 2019.
# Xavier Sellier <contact@binogure-studio.com>, 2019.
-# Sofiane <Sofiane-77@caramail.fr>, 2019, 2021.
+# Sofiane <Sofiane-77@caramail.fr>, 2019, 2021, 2022.
# Camille Mohr-Daurat <pouleyketchoup@gmail.com>, 2019.
# Pierre Stempin <pierre.stempin@gmail.com>, 2019.
# Pierre Caye <pierrecaye@laposte.net>, 2020, 2021, 2022.
@@ -99,13 +98,14 @@
# Nathan Hamy <hamynathan92@gmail.com>, 2022.
# HOUA <ninjacowzx@gmail.com>, 2022.
# DinosaurHorseSword <ewenlandry@mailfence.com>, 2022.
+# Arnaud Lier <arnaud@ric-rac.org>, 2022.
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: 2022-06-29 10:04+0000\n"
-"Last-Translator: DinosaurHorseSword <ewenlandry@mailfence.com>\n"
+"PO-Revision-Date: 2022-07-03 00:44+0000\n"
+"Last-Translator: Sofiane <Sofiane-77@caramail.fr>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -375,7 +375,7 @@ msgstr ""
#: core/io/stream_peer.cpp
msgid "Big Endian"
-msgstr ""
+msgstr "Gros-boutiste"
#: core/io/stream_peer.cpp
msgid "Data Array"
@@ -483,6 +483,11 @@ msgstr "Méta"
msgid "Command"
msgstr "Commande"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (physique)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -927,7 +932,7 @@ msgstr ""
#: core/register_core_types.cpp
msgid "TCP"
-msgstr "PCT (Protocole de Contrôle de Transmissions)"
+msgstr "TCP"
#: core/register_core_types.cpp
msgid "Connect Timeout Seconds"
@@ -5667,6 +5672,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Sélection de la GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18914,6 +18924,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Le paquet doit comporter au moins un séparateur « . »."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Nœud Personnalisé"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18922,6 +18937,14 @@ msgstr ""
msgid "Export Format"
msgstr "Chemin d'exportation"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "Min SDK"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "Target SDK"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18965,15 +18988,6 @@ msgstr "Inspecter l'instance précédente"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "SDK Minimal"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Cible"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19012,14 +19026,12 @@ msgid "OpenGL Debug"
msgstr "Ouvrir"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Features"
-msgstr "Fonctionnalités"
+msgstr "Fonctionnalités XR"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "XR Mode"
-msgstr "Mode navigation"
+msgstr "Mode XR"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -19226,17 +19238,16 @@ msgstr "« Use Custom Build » doit être activé pour utiliser les plugins."
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
-"« Hand Tracking » est valide uniquement lorsque le « Mode Xr » est « Oculus "
+"« Hand Tracking » est valide uniquement lorsque le « Mode XR » est « Oculus "
"Mobile VrApi »."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
-"« Passthrough » est valide uniquement lorsque le « Xr Mode » est « Oculus "
-"Mobile VrApi »."
+"« Passthrough » est valide uniquement lorsque le « Mode XR » est « OpenXR »."
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
@@ -19246,24 +19257,44 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
-"Changer « Min Sdk » est valide uniquement lorsque l'option « Use Custom "
+"Changer « Min SDK » est valide uniquement lorsque l'option « Use Custom "
"Build » est activée."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
-"Changer « Target Sdk » est valide uniquement lorsque l'option « Use Custom "
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+"Changer « Target SDK » est valide uniquement lorsque l'option « Use Custom "
"Build » est activée."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
-"La version « Target Sdk » doit être supérieure ou égale à la version « Min "
-"Sdk »."
+"La version « Target SDK » doit être supérieure ou égale à la version « Min "
+"SDK »."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
@@ -20976,7 +21007,7 @@ msgstr "Zoomer"
msgid "Custom Viewport"
msgstr "1 vue"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21747,6 +21778,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Liaison"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Choisissez distance :"
@@ -21755,6 +21791,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Choisissez distance :"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Options avancées"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activer"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21772,16 +21823,6 @@ msgstr "Retourner horizontalement"
msgid "Max Speed"
msgstr "Vitesse :"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Choisissez distance :"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activer"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -22876,7 +22917,7 @@ msgstr "Aimanter au pixel"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
msgid "Billboard"
-msgstr ""
+msgstr "Billboard"
#: scene/3d/label_3d.cpp scene/3d/sprite_3d.cpp
#, fuzzy
@@ -25226,6 +25267,11 @@ msgstr "Dossier :"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Sélection uniquement"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activer"
@@ -25627,18 +25673,6 @@ msgstr "Chemin d'exportation"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Ce Viewport n'est pas sélectionné comme cible de rendu. Si vous avez "
-"l'intention d'afficher son contenu directement à l'écran, rattachez-le à un "
-"nœud de type Control afin qu'il en obtienne une taille. Sinon, faites-en une "
-"RenderTarget et assignez sa texture à un nœud pouvant l'afficher."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25646,6 +25680,15 @@ msgstr ""
"dans les deux sens pour que le rendu soit possible."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
@@ -27098,14 +27141,12 @@ msgid "Point Size"
msgstr "Vue de devant"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Billboard Mode"
-msgstr "Mode Règle"
+msgstr "Mode billboard"
#: scene/resources/material.cpp
-#, fuzzy
msgid "Billboard Keep Scale"
-msgstr "Mode Règle"
+msgstr "Garder l'échelle du billboard"
#: scene/resources/material.cpp
msgid "Grow"
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 04e014ed77..65ffebf3e5 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -393,6 +393,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Scagairí..."
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5291,6 +5296,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17820,6 +17829,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Cruthaigh"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17827,6 +17841,15 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Nód Cumaisc2"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17863,15 +17886,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Nód Cumaisc2"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18093,12 +18107,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18107,17 +18121,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19656,7 +19690,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20339,6 +20373,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20347,29 +20385,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Scagairí..."
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Scagairí..."
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Scagairí..."
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23391,6 +23434,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Scagairí..."
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Scagairí..."
@@ -23752,16 +23800,17 @@ msgstr "Cosán"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
index 27b15829fa..c8dd75ade3 100644
--- a/editor/translations/gl.po
+++ b/editor/translations/gl.po
@@ -425,6 +425,11 @@ msgstr ""
msgid "Command"
msgstr "Comunidade"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fotograma de Física %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5642,6 +5647,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Encadrar Selección"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18796,6 +18806,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Cortar Nodos"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18804,6 +18819,16 @@ msgstr ""
msgid "Export Format"
msgstr "Formato"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Tamaño: "
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Obxectivo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18843,16 +18868,6 @@ msgstr "Anterior Pestana"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Tamaño: "
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Obxectivo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19102,12 +19117,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19116,17 +19131,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20782,7 +20817,7 @@ msgstr "Aumentar Zoom"
msgid "Custom Viewport"
msgstr "1 Ventá"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21524,6 +21559,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Pegar Animación"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Elexir unha Escena Principal"
@@ -21532,6 +21572,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avanzado"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21549,15 +21603,6 @@ msgstr "Horizontal:"
msgid "Max Speed"
msgstr "Velocidade:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr ""
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activar"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24887,6 +24932,11 @@ msgstr "Cartafol:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Só a Selección"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activar"
@@ -25283,18 +25333,6 @@ msgid "Viewport Path"
msgstr "1 Ventá"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Esta Mini-Ventá (Viewport) no está configurada como obxectivo de "
-"renderizado. Se quere que o seu contido se mostre directamente na pantalla, "
-"convértao nun nodo fillo dun nodo Control para que poida recibir dimensións. "
-"Ou ben, fágao un RenderTarget e asigne a súa textura a algún nodo."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25304,6 +25342,15 @@ msgstr ""
"renderizar nada."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/he.po b/editor/translations/he.po
index 22cf33ba52..d37f806bb7 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -423,6 +423,11 @@ msgstr ""
msgid "Command"
msgstr "פיקוד"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "פיזיקה"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5557,6 +5562,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap מילוי הבחירה"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18932,6 +18942,11 @@ msgid "The package must have at least one '.' separator."
msgstr "החבילה חייבת לכלול לפחות מפריד '.' ×חד."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "גזירת מפרקי×"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18940,6 +18955,16 @@ msgstr ""
msgid "Export Format"
msgstr "×™×™×¦×•× ×ž×™×–×"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "מבט קדמי"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "נתיב המש×ב"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18980,16 +19005,6 @@ msgstr "בדיקת המופע הקוד×"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "מבט קדמי"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "נתיב המש×ב"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19244,13 +19259,13 @@ msgstr "חובה ל×פשר ״שימוש בבניה מות×מת ×ישית״ ×›
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr "\"Hand Tracking\" תקף רק ×›×שר \"מצב Xr\" ×”×•× \"Oculus Mobile VR\"."
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Hand Tracking\" תקף רק ×›×שר \"מצב Xr\" ×”×•× \"Oculus Mobile VR\"."
#: platform/android/export/export_plugin.cpp
@@ -19259,17 +19274,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20942,7 +20977,7 @@ msgstr "התקרבות"
msgid "Custom Viewport"
msgstr "מבט תחתי"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21685,6 +21720,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "קישור"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "בחירת מרחק:"
@@ -21693,6 +21733,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "בחירת מרחק:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "מתקד×"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "הפעלה"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21709,16 +21764,6 @@ msgstr ""
msgid "Max Speed"
msgstr "מהירות (FPS):"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "בחירת מרחק:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "הפעלה"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25074,6 +25119,11 @@ msgstr "יצירת תיקייה"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "בחירה בלבד"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "הפעלה"
@@ -25476,17 +25526,6 @@ msgid "Viewport Path"
msgstr "×™×™×¦×•× ×ž×™×–×"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"חלון תצוגה ×–×” ×ינו מוגדר כיעד עיבוד. להצגת התוכן ישירות למסך, יש להפוך ×ותו "
-"לצ××¦× ×©×œ בקר כדי שיקבל גודל. ×ו להפוך ×ותו ל-RenderTarget ולשייך ×ת ×”×ž×¨×§× "
-"הפנימי שלו למפרק כלשהו לתצוגה."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25494,6 +25533,15 @@ msgid ""
msgstr "גודל חלון התצוגה חייב להיות גדול מ-0 על מנת להציג משהו."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index a14fd36f4a..0e6bb551e4 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -406,6 +406,11 @@ msgstr ""
msgid "Command"
msgstr "समà¥à¤¦à¤¾à¤¯"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "फिजिकà¥à¤¸ फà¥à¤°à¥‡à¤® %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5562,6 +5567,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "सभी खंड"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18576,6 +18586,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18584,6 +18599,16 @@ msgstr ""
msgid "Export Format"
msgstr "à¤à¤¨à¥€à¤®à¥‡à¤¶à¤¨ परिवरà¥à¤¤à¤¨ परिणत"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "आकार: "
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "नोड हटाà¤à¤‚"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18622,16 +18647,6 @@ msgstr "पिछला टैब"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "आकार: "
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "नोड हटाà¤à¤‚"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18872,12 +18887,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18886,17 +18901,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20534,7 +20569,7 @@ msgstr "बड़ा करो"
msgid "Custom Viewport"
msgstr "वà¥à¤¯à¥‚पोरà¥à¤Ÿ चà¥à¤¨à¥‡à¤‚"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21247,6 +21282,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "कोनà¥à¤¸à¥à¤Ÿà¤¨à¥à¤Ÿ"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "à¤à¤• मà¥à¤–à¥à¤¯ दृशà¥à¤¯ चà¥à¤¨à¥‡à¤‚"
@@ -21255,29 +21295,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "अगà¥à¤°à¤µà¤°à¥à¤¤à¥€"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "सकà¥à¤°à¤¿à¤¯ करे"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "सकà¥à¤°à¤¿à¤¯ करे"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24471,6 +24516,11 @@ msgstr "फ़ोलà¥à¤¡à¤°:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "सिरà¥à¤« चयन किये हà¥à¤"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "सकà¥à¤°à¤¿à¤¯ करे"
@@ -24865,16 +24915,17 @@ msgstr "फ़ोकस पाथ"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index 9a3dabefb3..c1a9a444cc 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -408,6 +408,11 @@ msgstr ""
msgid "Command"
msgstr "Zajednica"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Omogući"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5381,6 +5386,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Izbriši Odabir"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18135,6 +18145,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Pomakni Bezier ToÄke"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18143,6 +18158,16 @@ msgstr ""
msgid "Export Format"
msgstr "Izvoz"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Glavna skripta:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Premjesti Ävor(node)"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18179,16 +18204,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Glavna skripta:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Premjesti Ävor(node)"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18419,12 +18434,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18433,17 +18448,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20025,7 +20060,7 @@ msgstr "Zumiraj"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20728,6 +20763,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Zalijepi Animaciju"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Instaliraj"
@@ -20736,29 +20776,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Napredno"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Omogući"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Omogući"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23883,6 +23928,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Samo odabir"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Omogući"
@@ -24260,16 +24310,17 @@ msgstr "Put"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index 62f30698a3..5bfd5b0995 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -445,6 +445,11 @@ msgstr ""
msgid "Command"
msgstr "Közösség"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fizika Keret %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5670,6 +5675,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Kijelölés Keretezése"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18763,6 +18773,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Node-ok kivágása"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18771,6 +18786,16 @@ msgstr ""
msgid "Export Format"
msgstr "Exportálási Útvonal"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Körvonal Mérete:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Cél Felület:"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18810,16 +18835,6 @@ msgstr "Előző lap"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Körvonal Mérete:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Cél Felület:"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19065,12 +19080,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19079,17 +19094,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20740,7 +20775,7 @@ msgstr "Nagyítás"
msgid "Custom Viewport"
msgstr "Nézet Megjelenítése"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21476,6 +21511,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Véletlenszerű Forgatás:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Válasszon egy Fő Jelenetet"
@@ -21484,29 +21524,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Speciális"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Engedélyezés"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Engedélyezés"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24797,6 +24842,11 @@ msgstr "Mappa:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Csak kijelölés"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Engedélyezés"
@@ -25199,20 +25249,17 @@ msgstr "Exportálási Útvonal"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"Ez a nézetablak nincs beállítva leképezési célnak. Ha azt szeretné, hogy a "
-"tartalma közvetlenül a képernyőn jelenjen meg, tegye azt egy Control "
-"gyermekévé, hogy így kapjon méretet. Ellenkező esetben tegye RenderTarget-"
-"té, és állítsa hozzá a belső textúráját valamilyen node-hoz kirajzolásra."
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/id.po b/editor/translations/id.po
index 4d71521032..57c1a69e92 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -425,6 +425,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Perintah"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Secara fisik)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5601,6 +5606,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Tombol Ekstra Mouse Navigasi Riwayat"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Isi Seleksi GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Penampilan"
@@ -18874,6 +18884,11 @@ msgstr "Package setidaknya harus memiliki sebuah pemisah '.'."
#: platform/android/export/export_plugin.cpp
#, fuzzy
+msgid "Custom Build"
+msgstr "Gunakan Direktori Pengguna Kustom"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid "Use Custom Build"
msgstr "Gunakan Direktori Pengguna Kustom"
@@ -18882,6 +18897,16 @@ msgstr "Gunakan Direktori Pengguna Kustom"
msgid "Export Format"
msgstr "Lokasi Ekspor"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Ukuran Garis Tepi:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "FPS Sasaran"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18924,16 +18949,6 @@ msgstr "Inspeksi Instance Sebelumnya"
msgid "Code"
msgstr "Kode"
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Ukuran Garis Tepi:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "FPS Sasaran"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19174,7 +19189,7 @@ msgstr "\"Gunakan Build Custom\" harus diaktifkan untuk menggunakan plugin."
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Pelacakan Tangan\" hanya valid ketika \"Mode Xr\" bernilai \"Oculus Mobile "
@@ -19182,7 +19197,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Pelacakan Tangan\" hanya valid ketika \"Mode Xr\" bernilai \"Oculus Mobile "
"VR\"."
@@ -19195,20 +19210,41 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Expor AAB\" hanya bisa valid ketika \"Gunakan Build Custom\" diaktifkan."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Expor AAB\" hanya bisa valid ketika \"Gunakan Build Custom\" diaktifkan."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"Versi \"Target SDK\" harus lebih tinggi atau sama dengan versi \"Min SDK\"."
@@ -20881,7 +20917,7 @@ msgstr "Perbesar Pandangan"
msgid "Custom Viewport"
msgstr "Penampil Kustom"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21627,6 +21663,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Mengikat"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Target Jarak yang Diinginkan"
@@ -21635,6 +21676,21 @@ msgid "Target Desired Distance"
msgstr "Target Jarak yang Diinginkan"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Pilih Jarak:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Lanjut"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktifkan"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21651,16 +21707,6 @@ msgstr "Balik secara Horizontal"
msgid "Max Speed"
msgstr "Kecepatan Maks"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Pilih Jarak:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktifkan"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -25037,6 +25083,11 @@ msgstr "Direktori:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Hanya yang Dipilih"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktifkan"
@@ -25443,19 +25494,6 @@ msgid "Viewport Path"
msgstr "Lokasi Ekspor"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Viewport ini tidak diatur sebagai target render. Jika anda berniat untuk "
-"menampilkan konten-kontennya secara langsung ke layar, jadikan viewport ini "
-"sebagai child dari sebuah Control agar ia bisa memperoleh ukuran. Jika "
-"tidak, jadikan sebagai RenderTarget dan tetapkan tekstur internal nya ke "
-"beberapa node untuk ditampilkan."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25463,6 +25501,15 @@ msgid ""
msgstr "Ukuran viewport harus lebih besar dari 0 untuk me-render apa pun."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/is.po b/editor/translations/is.po
index 105220c71e..d5353421d4 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -401,6 +401,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5368,6 +5372,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Allt úrvalið"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18081,6 +18090,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Tvíteknir lyklar"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18089,6 +18103,15 @@ msgstr ""
msgid "Export Format"
msgstr "Breyta umbreytingu"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Anim DELETE-lyklar"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18125,15 +18148,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Anim DELETE-lyklar"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18361,12 +18375,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18375,17 +18389,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19932,7 +19966,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20625,6 +20659,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20633,29 +20671,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Fjarlægja val"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Fjarlægja val"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Fjarlægja val"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23706,6 +23749,11 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Afrita val"
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -24077,16 +24125,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 074bb4259d..e693139e21 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -68,13 +68,14 @@
# Alfonso Scarpino <alfonso.scarpino@gmail.com>, 2022.
# Federico Caprini <caprinifede@gmail.com>, 2022.
# Alessandro Casalino <alessandro.casalino93@gmail.com>, 2022.
+# conecat <ilgrandemax190@gmail.com>, 2022.
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: 2022-06-26 16:16+0000\n"
-"Last-Translator: Mirko <miknsop@gmail.com>\n"
+"PO-Revision-Date: 2022-07-04 05:16+0000\n"
+"Last-Translator: conecat <ilgrandemax190@gmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
"Language: it\n"
@@ -419,14 +420,12 @@ msgid "Max Size (KB)"
msgstr "Dimensione Massima (KB)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Modalità spostamento"
+msgstr "Modalità Mouse"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Elimina Input"
+msgstr "Usa Input Accumulato"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -453,6 +452,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Comando"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Fisico)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -1237,9 +1241,8 @@ msgid "Animation"
msgstr "Animazione"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing"
-msgstr "Easing"
+msgstr "Allentamento"
#: editor/animation_track_editor.cpp
msgid "Anim Multi Change Keyframe Time"
@@ -1353,14 +1356,12 @@ msgid "Time (s):"
msgstr "Tempo (s):"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Position:"
-msgstr "Posizione"
+msgstr "Posizione:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Rotation:"
-msgstr "Rotazione"
+msgstr "Rotazione:"
#: editor/animation_track_editor.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -1382,9 +1383,8 @@ msgid "(Invalid, expected type: %s)"
msgstr "Template di esportazione non valido:"
#: editor/animation_track_editor.cpp
-#, fuzzy
msgid "Easing:"
-msgstr "Easing"
+msgstr "Allentamento:"
#: editor/animation_track_editor.cpp
#, fuzzy
@@ -5573,6 +5573,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Uso dei tasti aggiuntivi del mouse per navigare la cronologia"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Selezione GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aspetto"
@@ -16241,8 +16246,9 @@ msgid "Flush stdout On Print"
msgstr "Svuota stdout Alla Stampa"
#: main/main.cpp servers/visual_server.cpp
+#, fuzzy
msgid "Logging"
-msgstr ""
+msgstr "Logging"
#: main/main.cpp
msgid "File Logging"
@@ -18562,6 +18568,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Il pacchetto deve avere almeno un \".\" separatore."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Utilizza Build Personalizzata"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Utilizza Build Personalizzata"
@@ -18569,6 +18580,14 @@ msgstr "Utilizza Build Personalizzata"
msgid "Export Format"
msgstr "Formato Esportazione"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "SDK Min"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "Target SDK"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18607,14 +18626,6 @@ msgstr "Elimina Installazione Precedente"
msgid "Code"
msgstr "Codice"
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "SDK Min"
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr "Target SDK"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr "Pacchetto"
@@ -18856,7 +18867,7 @@ msgstr "Per utilizzare i plugin \"Use Custom Build\" deve essere abilitato."
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è impostato su \"Oculus "
@@ -18864,7 +18875,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è impostato su \"Oculus "
"Mobile VR\"."
@@ -18877,20 +18888,40 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Export AAB\" è valido soltanto quanto \"Use Custom Build\" è abilitato."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Export AAB\" è valido soltanto quanto \"Use Custom Build\" è abilitato."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20584,7 +20615,7 @@ msgstr "Ingrandisci"
msgid "Custom Viewport"
msgstr "1 Vista"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20641,13 +20672,14 @@ msgid "Smoothing"
msgstr "Graduale"
#: scene/2d/camera_2d.cpp
+#, fuzzy
msgid "H"
-msgstr ""
+msgstr "H"
#: scene/2d/camera_2d.cpp
#, fuzzy
msgid "V"
-msgstr "UV"
+msgstr "V"
#: scene/2d/camera_2d.cpp
#, fuzzy
@@ -20958,7 +20990,7 @@ msgstr "Propagazione"
#: scene/resources/particles_material.cpp
#, fuzzy
msgid "Initial Velocity"
-msgstr "Inizializza"
+msgstr "Velocità iniziale"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20969,8 +21001,9 @@ msgstr "Velocità"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp servers/physics_2d_server.cpp
#: servers/physics_server.cpp
+#, fuzzy
msgid "Angular Velocity"
-msgstr ""
+msgstr "Velocità angolare"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -20982,13 +21015,13 @@ msgstr "Velocità"
#: scene/resources/particles_material.cpp
#, fuzzy
msgid "Orbit Velocity"
-msgstr "Orbita la visuale a destra"
+msgstr "Velocità orbitale"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
#, fuzzy
msgid "Linear Accel"
-msgstr "Lineare"
+msgstr "Accelerazione lineare"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
@@ -21009,13 +21042,15 @@ msgstr "Dividi Curva"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
+#, fuzzy
msgid "Radial Accel"
-msgstr ""
+msgstr "Accelerazione radiale"
#: scene/2d/cpu_particles_2d.cpp scene/3d/cpu_particles.cpp
#: scene/resources/particles_material.cpp
+#, fuzzy
msgid "Tangential Accel"
-msgstr ""
+msgstr "Accelerazione tangenziale"
#: scene/2d/cpu_particles_2d.cpp scene/2d/joints_2d.cpp
#: scene/3d/cpu_particles.cpp scene/3d/physics_body.cpp
@@ -21368,6 +21403,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Associazione"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Scegli la Distanza:"
@@ -21376,6 +21416,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Scegli la Distanza:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Opzioni avanzate"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Abilita"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21393,16 +21448,6 @@ msgstr "Ribalta orizzontalmente"
msgid "Max Speed"
msgstr "Velocità:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Scegli la Distanza:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Abilita"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -21866,12 +21911,14 @@ msgstr ""
"Skeleton2D e impostane una."
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
+#, fuzzy
msgid "Hframes"
-msgstr ""
+msgstr "Hframes"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
+#, fuzzy
msgid "Vframes"
-msgstr ""
+msgstr "Vframes"
#: scene/2d/sprite.cpp scene/3d/sprite_3d.cpp
#, fuzzy
@@ -22129,8 +22176,9 @@ msgstr "Impacchettando"
#: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp
#: scene/3d/reflection_probe.cpp
+#, fuzzy
msgid "Interior"
-msgstr ""
+msgstr "Interno"
#: scene/3d/baked_lightmap.cpp
msgid "Finding meshes and lights"
@@ -22270,8 +22318,9 @@ msgid "Projection"
msgstr "Proiezione"
#: scene/3d/camera.cpp
+#, fuzzy
msgid "FOV"
-msgstr ""
+msgstr "FOV"
#: scene/3d/camera.cpp
#, fuzzy
@@ -22284,8 +22333,9 @@ msgid "Near"
msgstr "Vicino"
#: scene/3d/camera.cpp
+#, fuzzy
msgid "Far"
-msgstr ""
+msgstr "Lontano"
#: scene/3d/camera.cpp scene/3d/collision_polygon.cpp scene/3d/spring_arm.cpp
#: scene/gui/control.cpp scene/resources/default_theme/default_theme.cpp
@@ -22470,8 +22520,9 @@ msgstr ""
"Per rimuovere questo avviso, disattiva la proprietà Compress di GIProbe."
#: scene/3d/gi_probe.cpp
+#, fuzzy
msgid "Subdiv"
-msgstr ""
+msgstr "Subdiv"
#: scene/3d/gi_probe.cpp
#, fuzzy
@@ -22622,8 +22673,9 @@ msgid "Depth Range"
msgstr "Profondità"
#: scene/3d/light.cpp
+#, fuzzy
msgid "Omni"
-msgstr ""
+msgstr "Omni"
#: scene/3d/light.cpp
#, fuzzy
@@ -23363,8 +23415,9 @@ msgid "There should only be one RoomManager in the SceneTree."
msgstr "Ci dovrebbe essere un solo RoomManager nello SceneTree."
#: scene/3d/room_manager.cpp
+#, fuzzy
msgid "Main"
-msgstr ""
+msgstr "Principale"
#: scene/3d/room_manager.cpp scene/animation/animation_blend_tree.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
@@ -23607,8 +23660,9 @@ msgid "Spring Length"
msgstr ""
#: scene/3d/sprite_3d.cpp scene/gui/graph_edit.cpp
+#, fuzzy
msgid "Opacity"
-msgstr ""
+msgstr "Opacità"
#: scene/3d/sprite_3d.cpp scene/resources/material.cpp
#, fuzzy
@@ -23729,8 +23783,9 @@ msgid "Lightmap Scale"
msgstr ""
#: scene/3d/visual_instance.cpp
+#, fuzzy
msgid "LOD"
-msgstr ""
+msgstr "LOD"
#: scene/3d/visual_instance.cpp scene/animation/skeleton_ik.cpp
#: scene/resources/material.cpp
@@ -24041,8 +24096,9 @@ msgid "Stretch Mode"
msgstr "Modalità di Selezione"
#: scene/gui/aspect_ratio_container.cpp scene/gui/box_container.cpp
+#, fuzzy
msgid "Alignment"
-msgstr ""
+msgstr "Allineamento"
#: scene/gui/base_button.cpp
#, fuzzy
@@ -24827,6 +24883,11 @@ msgstr "Cartella:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Solo nella selezione"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Abilita"
@@ -25234,19 +25295,6 @@ msgstr "Percorso di Esportazione"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Questo viewport non è impostato come target di render. Se si vuole che il "
-"suo contenuto venga direttamente visualizzato sullo schermo, renderlo figlio "
-"di un Control, in modo che possa ottenere una dimensione. Altrimenti, "
-"renderlo un RenderTarget e assegnare la sua texture interna a qualche nodo "
-"per la visualizzazione."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25254,6 +25302,15 @@ msgstr ""
"entrambi i lati per visualizzare qualcosa."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index a699aeb597..3abcd5529f 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -430,6 +430,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (物ç†çš„)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5567,6 +5572,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap ã®é¸æŠž"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外観"
@@ -18661,6 +18671,11 @@ msgid "The package must have at least one '.' separator."
msgstr "パッケージã«ã¯ä¸€ã¤ä»¥ä¸Šã®åŒºåˆ‡ã‚Šæ–‡å­— '.' ãŒå¿…è¦ã§ã™ã€‚"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ノードを切りå–ã‚‹"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18669,6 +18684,15 @@ msgstr ""
msgid "Export Format"
msgstr "エクスãƒãƒ¼ãƒˆå…ˆã®ãƒ‘ス"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "アウトラインã®ã‚µã‚¤ã‚º:"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "ターゲットSDK"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18712,15 +18736,6 @@ msgstr "å‰ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’調ã¹ã‚‹"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "アウトラインã®ã‚µã‚¤ã‚º:"
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr "ターゲットSDK"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18968,15 +18983,17 @@ msgstr ""
"ã«ãªã£ã¦ã„ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" 㯠\"Xr Mode\" ㌠\"Oculus Mobile VrApi\" ã¾ãŸã¯ "
"\"OpenXR\" ã®å ´åˆã«ã®ã¿æœ‰åйã§ã™ã€‚"
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Passthrough\" 㯠\"Xr Mode\" ㌠\"OpenXR\" ã®å ´åˆã«ã®ã¿æœ‰åйã§ã™ã€‚"
#: platform/android/export/export_plugin.cpp
@@ -18985,20 +19002,43 @@ msgstr ""
"\"Export AAB\" 㯠\"Use Custom Build\" ãŒæœ‰åйã§ã‚ã‚‹å ´åˆã«ã®ã¿æœ‰åйã«ãªã‚Šã¾ã™ã€‚"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Min Sdk\" ã®å¤‰æ›´ã¯ \"Use Custom Build\" ãŒæœ‰åйã§ã‚ã‚‹å ´åˆã«ã®ã¿æœ‰åйã§ã™ã€‚"
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Target Sdk\" ã®å¤‰æ›´ã¯ \"Use Custom Build\" ãŒæœ‰åйã§ã‚ã‚‹å ´åˆã«ã®ã¿æœ‰åйã§ã™ã€‚"
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"\"Target Sdk\" ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ \"Min Sdk\" ãƒãƒ¼ã‚¸ãƒ§ãƒ³ä»¥ä¸Šã§ãªã‘れã°ãªã‚Šã¾ã›ã‚“。"
@@ -20681,7 +20721,7 @@ msgstr "ズーム"
msgid "Custom Viewport"
msgstr "1 ビューãƒãƒ¼ãƒˆ"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -21441,6 +21481,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ãƒã‚¤ãƒ³ãƒ‰"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "è·é›¢ã‚’å–å¾—:"
@@ -21449,6 +21494,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "è·é›¢ã‚’å–å¾—:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "高度ãªè¨­å®š"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "有効"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21466,16 +21526,6 @@ msgstr "å·¦å³å転"
msgid "Max Speed"
msgstr "速度:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "è·é›¢ã‚’å–å¾—:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "有効"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -24919,6 +24969,11 @@ msgstr "フォルダー:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "é¸æŠžç¯„å›²ã®ã¿"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "有効"
@@ -25327,22 +25382,19 @@ msgstr "エクスãƒãƒ¼ãƒˆå…ˆã®ãƒ‘ス"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"ã“ã®ãƒ“ューãƒãƒ¼ãƒˆã¯ãƒ¬ãƒ³ãƒ€ãƒ¼ ターゲットã¨ã—ã¦è¨­å®šã•れã¦ã„ã¾ã›ã‚“。コンテンツを画"
-"é¢ã«ç›´æŽ¥è¡¨ç¤ºã™ã‚‹å ´åˆã¯ã€ã‚µã‚¤ã‚ºã‚’å–å¾—ã§ãるよã†ã«ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã®å­ã«ã—ã¾ã™ã€‚ã"
-"れ以外ã®å ´åˆã¯ã€RenderTarget ã«ã—ã¦ã€ãã®å†…部テクスãƒãƒ£ã‚’表示ã™ã‚‹ãƒŽãƒ¼ãƒ‰ã«å‰²ã‚Š"
-"当ã¦ã¾ã™ã€‚"
+"レンダーã™ã‚‹ã«ã¯Viewportã®ç¸¦æ¨ªãれãžã‚ŒãŒ2ピクセル以上ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
-"レンダーã™ã‚‹ã«ã¯Viewportã®ç¸¦æ¨ªãれãžã‚ŒãŒ2ピクセル以上ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: scene/main/viewport.cpp
msgid "ARVR"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index caf07e1063..14599ca68e 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -407,6 +407,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "დáƒáƒ›áƒáƒ™áƒáƒ•შირებელი სიგნáƒáƒšáƒ˜:"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5496,6 +5501,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "ყველრმáƒáƒœáƒ˜áƒ¨áƒœáƒ•áƒ"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18503,6 +18513,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ¡áƒáƒ¦áƒ”ბების áƒáƒ¡áƒšáƒ˜áƒ¡ შექმნáƒ"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18511,6 +18526,16 @@ msgstr ""
msgid "Export Format"
msgstr "áƒáƒœáƒ˜áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ áƒ“áƒáƒ¥áƒ›áƒœáƒ˜áƒ¡ ცვლილებáƒ"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების შემსწáƒáƒ áƒ”ბელი"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "წáƒáƒ¨áƒšáƒ"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18547,16 +18572,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "დáƒáƒ›áƒáƒ™áƒ˜áƒ“ებულებების შემსწáƒáƒ áƒ”ბელი"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "წáƒáƒ¨áƒšáƒ"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18791,12 +18806,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18805,17 +18820,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20411,7 +20446,7 @@ msgstr "ზუმის გáƒáƒ–რდáƒ"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21119,6 +21154,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "მუდმივი"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "დáƒáƒ§áƒ”ნებáƒ"
@@ -21127,29 +21167,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "დáƒáƒ‘áƒáƒšáƒáƒœáƒ¡áƒ”ბული"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "დáƒáƒ›áƒáƒ™áƒáƒ•შირებელი სიგნáƒáƒšáƒ˜:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "დáƒáƒ›áƒáƒ™áƒáƒ•შირებელი სიგნáƒáƒšáƒ˜:"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24305,6 +24350,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ მხáƒáƒšáƒáƒ“"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "დáƒáƒ›áƒáƒ™áƒáƒ•შირებელი სიგნáƒáƒšáƒ˜:"
@@ -24687,16 +24737,17 @@ msgstr "გზáƒ"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/km.po b/editor/translations/km.po
index b58578c50d..32175987ef 100644
--- a/editor/translations/km.po
+++ b/editor/translations/km.po
@@ -385,6 +385,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5257,6 +5261,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17719,6 +17727,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Anim ផ្លាស់ប្ážáž¼ážš Transform"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17726,6 +17739,14 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17762,14 +17783,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -17988,12 +18001,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18002,17 +18015,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19520,7 +19553,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20184,6 +20217,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20192,27 +20229,31 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
+msgid "Avoidance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+msgid "Avoidance Enabled"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
+msgid "Time Horizon"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Max Speed"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp
@@ -23152,6 +23193,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23504,16 +23549,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index fb4bf92e30..8800745e09 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -421,6 +421,11 @@ msgstr "메타"
msgid "Command"
msgstr "명령"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (물리)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5468,6 +5473,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "마우스 부가 버튼으로 히스토리 둘러보기"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "그리드맵 ì„ íƒ"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "모습"
@@ -18634,6 +18644,11 @@ msgid "The package must have at least one '.' separator."
msgstr "패키지는 ì ì–´ë„ í•˜ë‚˜ì˜ '.' 분리 기호가 있어야 합니다."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "노드 잘ë¼ë‚´ê¸°"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18642,6 +18657,16 @@ msgstr ""
msgid "Export Format"
msgstr "경로 내보내기"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "윤곽선 í¬ê¸°:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Target(대ìƒ)"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18684,16 +18709,6 @@ msgstr "ì´ì „ ì¸ìŠ¤í„´ìŠ¤ 검사"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "윤곽선 í¬ê¸°:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Target(대ìƒ)"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18940,14 +18955,14 @@ msgstr "플러그ì¸ì„ 사용하려면 \"Use Custom Build\"ê°€ 활성화ë˜ì–´ì
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"ì† ì¶”ì \" ì€ \"Xr 모드\" ê°€ \"Oculus Mobile VR\"ì¼ ë•Œë§Œ 사용 가능합니다."
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"ì† ì¶”ì \" ì€ \"Xr 모드\" ê°€ \"Oculus Mobile VR\"ì¼ ë•Œë§Œ 사용 가능합니다."
@@ -18958,18 +18973,38 @@ msgstr "\"Export AAB\"는 \"Use Custom Build\"ê°€ í™œì„±í™”ëœ ê²½ìš°ì—ë§Œ 유í
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\"는 \"Use Custom Build\"ê°€ í™œì„±í™”ëœ ê²½ìš°ì—ë§Œ 유효합니다."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\"는 \"Use Custom Build\"ê°€ í™œì„±í™”ëœ ê²½ìš°ì—ë§Œ 유효합니다."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20653,7 +20688,7 @@ msgstr "줌 ì¸"
msgid "Custom Viewport"
msgstr "ë·°í¬íЏ 1ê°œ"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21418,6 +21453,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ë°”ì¸ë”©"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "거리 ì„ íƒ:"
@@ -21426,6 +21466,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "거리 ì„ íƒ:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "고급"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "활성화"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21443,16 +21498,6 @@ msgstr "수í‰ìœ¼ë¡œ 뒤집기"
msgid "Max Speed"
msgstr "ì†ë„:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "거리 ì„ íƒ:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "활성화"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24875,6 +24920,11 @@ msgstr "í´ë”:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "ì„ íƒ ì˜ì—­ë§Œ"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "활성화"
@@ -25285,22 +25335,19 @@ msgstr "경로 내보내기"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
-"ë·°í¬íŠ¸ë¥¼ ë Œë” ëŒ€ìƒìœ¼ë¡œ 설정하지 않았습니다. ë·°í¬íŠ¸ì˜ ë‚´ìš©ì„ í™”ë©´ì— ì§ì ‘ 표시"
-"하려면, Controlì˜ ìžì‹ 노드로 만들어서 í¬ê¸°ë¥¼ 얻어야 합니다. 그렇지 ì•Šì„ ê²½"
-"ìš°, í™”ë©´ì— í‘œì‹œí•˜ê¸° 위해서는 ë·°í¬íŠ¸ë¥¼ RenderTarget으로 만들고 ë‚´ë¶€ì ì¸ í…스처"
-"를 다른 ë…¸ë“œì— ì§€ì •í•´ì•¼ 합니다."
+"무엇ì´ë“  ë Œë”ë§í•˜ë ¤ë©´ ë·°í¬íЏ í¬ê¸°ê°€ 양쪽 ì°¨ì›ì—서 2픽셀 ì´ìƒì´ì–´ì•¼ 합니다."
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
-"무엇ì´ë“  ë Œë”ë§í•˜ë ¤ë©´ ë·°í¬íЏ í¬ê¸°ê°€ 양쪽 ì°¨ì›ì—서 2픽셀 ì´ìƒì´ì–´ì•¼ 합니다."
#: scene/main/viewport.cpp
msgid "ARVR"
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index 350bcb0352..51428b68f4 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -417,6 +417,11 @@ msgstr ""
msgid "Command"
msgstr "BendruomenÄ—"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fizikos Kadro %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5473,6 +5478,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Visas Pasirinkimas"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18503,6 +18513,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Transition Nodas"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18511,6 +18526,16 @@ msgstr ""
msgid "Export Format"
msgstr "Importuoti iš Nodo:"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Atidaryti Skriptų Editorių"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "TimeScale Nodas"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18547,16 +18572,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Atidaryti Skriptų Editorių"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "TimeScale Nodas"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18793,12 +18808,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18807,17 +18822,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20436,7 +20471,7 @@ msgstr "Priartinti"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21143,6 +21178,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Konstanta"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Diegti"
@@ -21151,29 +21191,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Įgalinti"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Įgalinti"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Įgalinti"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24339,6 +24384,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Pasirinkite Nodus, kuriuos norite importuoti"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Įgalinti"
@@ -24722,16 +24772,17 @@ msgstr "Importuoti iš Nodo:"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index c80bd29122..0d2e4afec9 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -419,6 +419,11 @@ msgstr ""
msgid "Command"
msgstr "Komūns"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fizikas kadrs %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5544,6 +5549,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Režģkartes izvēle"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18309,6 +18319,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Izgriezt mezglu(s)"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18317,6 +18332,16 @@ msgstr ""
msgid "Export Format"
msgstr "Eksportēt bibliotēku"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Galvenais Skripts:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Izdzēst Mezglu"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18356,16 +18381,6 @@ msgstr "IepriekšējÄ cilne"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Galvenais Skripts:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Izdzēst Mezglu"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18599,12 +18614,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18613,17 +18628,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20249,7 +20284,7 @@ msgstr "PalielinÄt"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20967,6 +21002,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Konstante"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Izvēlēties galveno ainu"
@@ -20975,29 +21015,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Papildus"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Iespējot"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Iespējot"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24206,6 +24251,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Tikai izvēlētais"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Iespējot"
@@ -24599,16 +24649,17 @@ msgstr "Fokusa ceļš"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index 5c3bfc87ff..b35fce0168 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -389,6 +389,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5274,6 +5278,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17759,6 +17767,10 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+msgid "Custom Build"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17766,6 +17778,15 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Јазол"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17802,15 +17823,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Јазол"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18031,12 +18043,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18045,17 +18057,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19568,7 +19600,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20236,6 +20268,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20244,27 +20280,31 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
+msgid "Avoidance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+msgid "Avoidance Enabled"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
+msgid "Time Horizon"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Max Speed"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp
@@ -23217,6 +23257,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23571,16 +23615,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index 7b247d8f78..b2f6c17059 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -394,6 +394,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5290,6 +5294,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17788,6 +17796,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "à´ªàµà´°à´µàµƒà´¤àµà´¤à´¿à´•ൾ:"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17796,6 +17809,14 @@ msgstr ""
msgid "Export Format"
msgstr "à´¤àµà´°à´¿à´®à´¾à´¨ പരിവർതàµà´¤à´¨à´‚ നോകàµà´•àµà´•"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr ""
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17832,14 +17853,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr ""
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18060,12 +18073,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18074,17 +18087,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19608,7 +19641,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20279,6 +20312,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20287,27 +20324,31 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
+msgid "Avoidance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+msgid "Avoidance Enabled"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
+msgid "Time Horizon"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Max Speed"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp
@@ -23295,6 +23336,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23650,16 +23695,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index d7aa4bd1aa..d9943d0a5e 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -394,6 +394,10 @@ msgstr ""
msgid "Command"
msgstr "समà¥à¤¦à¤¾à¤¯"
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5280,6 +5284,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17787,6 +17795,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "अâ€à¥…निमेशन टà¥à¤°à¥€"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17794,6 +17807,15 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "नोड हलवा"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17830,15 +17852,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "नोड हलवा"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18061,12 +18074,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18075,17 +18088,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19609,7 +19642,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20292,6 +20325,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20300,29 +20337,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "समकà¥à¤°à¤®à¤¿à¤¤ करा"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "समकà¥à¤°à¤®à¤¿à¤¤ करा"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "समकà¥à¤°à¤®à¤¿à¤¤ करा"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23322,6 +23364,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23678,16 +23724,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index b297eb52a3..a1955bb027 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -395,6 +395,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Perintah"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fizik"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5537,6 +5542,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Semua Pilihan"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18502,6 +18512,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Potong Nod"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18510,6 +18525,16 @@ msgstr ""
msgid "Export Format"
msgstr "Warna seragam."
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Saiz:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Cipta Nod"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18548,16 +18573,6 @@ msgstr "Tab sebelumnya"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Saiz:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Cipta Nod"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18800,12 +18815,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18814,17 +18829,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20453,7 +20488,7 @@ msgstr "Zum Masuk"
msgid "Custom Viewport"
msgstr "Tunjukkan Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21176,6 +21211,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Tampal Animasi"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Pilih Adegan Utama"
@@ -21184,29 +21224,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Lanjutan"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktifkan"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktifkan"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24450,6 +24495,11 @@ msgstr "Folder:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Pilihan Sahaja"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktifkan"
@@ -24847,16 +24897,17 @@ msgstr "Laluan Fokus"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index a545e4fc83..11bf857f4b 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -412,6 +412,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Kommando"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fysikk"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5721,6 +5726,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Slett Valgte"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19287,6 +19297,11 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
+msgid "Custom Build"
+msgstr "Bruk Tilpasset Brukerkatalog"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid "Use Custom Build"
msgstr "Bruk Tilpasset Brukerkatalog"
@@ -19295,6 +19310,16 @@ msgstr "Bruk Tilpasset Brukerkatalog"
msgid "Export Format"
msgstr "Eksporter Prosjekt"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Størrelse:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "MÃ¥l FPS"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19336,16 +19361,6 @@ msgstr "Forrige fane"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Størrelse:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "MÃ¥l FPS"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19591,12 +19606,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19605,17 +19620,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21283,7 +21318,7 @@ msgstr "Forstørr"
msgid "Custom Viewport"
msgstr "Vis hjelpere"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -22024,6 +22059,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Fyll"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Velg en HovedScene"
@@ -22032,6 +22072,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avansert"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktiver"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -22049,15 +22103,6 @@ msgstr "Vend horisontalt"
msgid "Max Speed"
msgstr "Hastighet (FPS):"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr ""
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktiver"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25366,6 +25411,11 @@ msgstr "Mappe:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Kun Valgte"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktiver"
@@ -25769,16 +25819,17 @@ msgstr "Eksporter Prosjekt"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 32d57b08b9..def707ac8b 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -484,6 +484,11 @@ msgstr ""
msgid "Command"
msgstr "Gemeenschap"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Physics Frame %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5714,6 +5719,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap-selectie vullen"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19143,6 +19153,11 @@ msgid "The package must have at least one '.' separator."
msgstr "De pakketnaam moet ten minste een '.' bevatten."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Knopen knippen"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19151,6 +19166,16 @@ msgstr ""
msgid "Export Format"
msgstr "Export Pad"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Omlijningsgrootte:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Doel"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -19194,16 +19219,6 @@ msgstr "Inspecteer vorige instantie"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Omlijningsgrootte:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Doel"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19453,7 +19468,7 @@ msgstr "\"Use Custom Build\" moet geactiveerd zijn om plugins te gebruiken."
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" is alleen geldig als \"Xr Mode\" op \"Oculus Mobile VR\" "
@@ -19461,7 +19476,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" is alleen geldig als \"Xr Mode\" op \"Oculus Mobile VR\" "
"staat."
@@ -19473,18 +19488,38 @@ msgstr "\"Export AAB\" is alleen geldig als \"Use Custom Build\" aan staat."
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\" is alleen geldig als \"Use Custom Build\" aan staat."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\" is alleen geldig als \"Use Custom Build\" aan staat."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21172,7 +21207,7 @@ msgstr "Inzoomen"
msgid "Custom Viewport"
msgstr "1 beeldvenster"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21944,6 +21979,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Binding"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Selecteerafstand:"
@@ -21952,6 +21992,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Selecteerafstand:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Geavanceerd"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Inschakelen"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21969,16 +22024,6 @@ msgstr "Horizontaal omdraaien"
msgid "Max Speed"
msgstr "Snelheid:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Selecteerafstand:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Inschakelen"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -25395,6 +25440,11 @@ msgstr "Map:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Alleen selectie"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Inschakelen"
@@ -25801,18 +25851,6 @@ msgid "Viewport Path"
msgstr "Export Pad"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Dit beeldvenster is niet ingesteld als renderdoelwit. Als de inhoud op het "
-"scherm getoond moet worden, moet je het een kind van een Control knoop "
-"maken, zodat het een grootte kan ontvangen. Anders, maak er een RenderTarget "
-"van en wijs zijn interne textuur toe aan een knoop om te tonen."
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25821,6 +25859,15 @@ msgstr ""
"De grootte van een Viewport moet groter zijn dan 0 om iets weer te geven."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index e174b8a673..9fdaafae3e 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -61,13 +61,14 @@
# Konrad <kobe-interactive@protonmail.com>, 2022.
# Pixel Zone - Godot Engine Tutorials <karoltomaszewskimusic@gmail.com>, 2022.
# DK0492 <doriankaczmarek28@gmail.com>, 2022.
+# Dawid Skubij <davidsd@tlen.pl>, 2022.
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: 2022-05-30 16:17+0000\n"
-"Last-Translator: DK0492 <doriankaczmarek28@gmail.com>\n"
+"PO-Revision-Date: 2022-07-05 23:51+0000\n"
+"Last-Translator: Dawid Skubij <davidsd@tlen.pl>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -76,7 +77,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -448,6 +449,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (fizyczny)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -714,9 +720,8 @@ msgstr "Kontrola wersji"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
-#, fuzzy
msgid "Input"
-msgstr "Input"
+msgstr "Wejście"
#: core/project_settings.cpp
msgid "UI Accept"
@@ -5616,6 +5621,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Wybór GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "WyglÄ…d"
@@ -18857,6 +18867,11 @@ msgstr "Paczka musi mieć co najmniej jedną kropkę jako separator."
#: platform/android/export/export_plugin.cpp
#, fuzzy
+msgid "Custom Build"
+msgstr "Użyj niestandardowego katalogu użytkownika"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid "Use Custom Build"
msgstr "Użyj niestandardowego katalogu użytkownika"
@@ -18865,6 +18880,16 @@ msgstr "Użyj niestandardowego katalogu użytkownika"
msgid "Export Format"
msgstr "Ścieżka eksportu"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Rozmiar zarysu:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Docelowa liczba klatek na sekundÄ™ (FPS)"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18908,16 +18933,6 @@ msgstr "Sprawdź poprzednią instancję"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Rozmiar zarysu:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Docelowa liczba klatek na sekundÄ™ (FPS)"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19166,15 +19181,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "\"Use Custom Build\" musi być włączone, by używać wtyczek."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" jest poprawne tylko, gdy \"Xr Mode\" jest \"Oculus Mobile "
"VrApi\" lub \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Passthrough\" jest poprawne tylko, gdy \"Xr Mode\" jest \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
@@ -19183,22 +19200,45 @@ msgstr ""
"\"Eksportuj AAB\" jest ważne tylko gdy \"Use Custom Build\" jest włączone."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Zmiana \"Min Sdk\" jest poprawna tylko, gdy \"Use Custom Build\" jest "
"włączone."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Zmiana \"Target Sdk\" jest poprawna tylko, gdy \"Use Custom Build\" jest "
"włączone."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr "Wersja \"Target Sdk\" musi być większa lub równa wersji \"Min Sdk\"."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20938,7 +20978,7 @@ msgstr "Przybliż"
msgid "Custom Viewport"
msgstr "1 widok"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21717,6 +21757,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "WiÄ…zanie"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Wybierz odległość:"
@@ -21725,6 +21770,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Wybierz odległość:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Zaawansowane"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Włącz"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21742,16 +21802,6 @@ msgstr "Odbij poziomo"
msgid "Max Speed"
msgstr "Szybkość:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Wybierz odległość:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Włącz"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -23582,9 +23632,8 @@ msgid "A RoomGroup should not be a child or grandchild of a Portal."
msgstr "RoomGroup nie powinien być potomkiem Portalu."
#: scene/3d/portal.cpp
-#, fuzzy
msgid "Portal Active"
-msgstr " [portale aktywne]"
+msgstr "Portal Aktywny"
#: scene/3d/portal.cpp scene/resources/occluder_shape_polygon.cpp
msgid "Two Way"
@@ -25209,6 +25258,11 @@ msgstr "Folder:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Tylko zaznaczenie"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Włącz"
@@ -25545,9 +25599,8 @@ msgid "Draw 2D Outlines"
msgstr "Utwórz obrys"
#: scene/main/scene_tree.cpp servers/visual_server.cpp
-#, fuzzy
msgid "Reflections"
-msgstr "Kierunki"
+msgstr "Odbicia"
#: scene/main/scene_tree.cpp
#, fuzzy
@@ -25620,18 +25673,6 @@ msgstr "Ścieżka eksportu"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Ten Viewport nie jest ustawiony jako Render Target. Jeśli chcesz wyświetlić "
-"jego zawartość na ekranie dodaj go jako dziecko węzła typu Control, aby "
-"otrzymał jakiś rozmiar. W przeciwnym wypadku ustawi opcję RenderTarget i "
-"przyporządkuj jego teksturę dla któregoś węzła."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25639,6 +25680,15 @@ msgstr ""
"cokolwiek renderować."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
@@ -26730,7 +26780,7 @@ msgstr "Warunek"
#: scene/resources/environment.cpp
msgid "Fog"
-msgstr ""
+msgstr "Mgła"
#: scene/resources/environment.cpp
#, fuzzy
@@ -26912,9 +26962,8 @@ msgstr ""
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
-#, fuzzy
msgid "2"
-msgstr "2D"
+msgstr "2"
#: scene/resources/environment.cpp
#: servers/audio/effects/audio_effect_chorus.cpp
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index f60daf2f7b..d0e041aba9 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -413,6 +413,11 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Paste yer Node"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5460,6 +5465,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Yar, Blow th' Selected Down!"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18559,6 +18569,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Slit th' Node"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18567,6 +18582,16 @@ msgstr ""
msgid "Export Format"
msgstr "Change yer Anim Transform"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Edit"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Slit th' Node"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18606,16 +18631,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Edit"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Slit th' Node"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18849,12 +18864,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18863,17 +18878,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20478,7 +20513,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21184,6 +21219,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Slit th' Node"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Edit"
@@ -21192,29 +21232,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Paste yer Node"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Paste yer Node"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Paste yer Node"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24349,6 +24394,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Slit th' Node"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Paste yer Node"
@@ -24731,16 +24781,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 7db8765ae3..edbc6971fb 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -407,6 +407,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Comando"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Físico)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5528,6 +5533,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Botões extra do Mouse para Navegar no Histórico"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Seleção de GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Aparência"
@@ -18620,6 +18630,11 @@ msgid "The package must have at least one '.' separator."
msgstr "O pacote deve ter pelo menos um separador '.'."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Usar Compilação Personalizada"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Usar Compilação Personalizada"
@@ -18628,6 +18643,16 @@ msgstr "Usar Compilação Personalizada"
msgid "Export Format"
msgstr "Exportar Caminho"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Tamanho do contorno:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Alvo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18671,16 +18696,6 @@ msgstr "Inspecionar instância anterior"
msgid "Code"
msgstr "Código"
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Tamanho do contorno:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Alvo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18936,15 +18951,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "\"Use Custom Build\" têm de estar ativa para usar os plugins."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Rastreamento de Mão\" só é válido quando \"Modo Xr\" é \"Oculus Mobile "
"VrApi\" ou \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Passthrough\" só é válido quando \"Modo Xr\" é \"OpenXR\"."
#: platform/android/export/export_plugin.cpp
@@ -18952,20 +18969,43 @@ msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
msgstr "\"Exportar AAB\" só é válido quando \"Use Custom Build\" está ativa."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Mudança de \"Min Sdk\" só é válida quando \"Use Custom Build\" está ativa."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Mudança de \"Target Sdk\" só é válida quando \"Use Custom Build\" está ativa."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"Versão de \"Target Sdk\" tem de ser maior ou igual à versão de \"Min Sdk\"."
@@ -20640,7 +20680,7 @@ msgstr "Aumentar Zoom"
msgid "Custom Viewport"
msgstr "1 Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21412,6 +21452,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Ligação"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Distância de escolha:"
@@ -21420,6 +21465,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Distância de escolha:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avançado"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Ativar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21437,16 +21497,6 @@ msgstr "Inverter na Horizontal"
msgid "Max Speed"
msgstr "Velocidade:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Distância de escolha:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Ativar"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -24886,6 +24936,11 @@ msgstr "Pasta:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Apenas seleção"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Ativar"
@@ -25298,18 +25353,6 @@ msgstr "Exportar Caminho"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Este viewport não está definida como alvo de Renderização. Se pretende "
-"apresentar o seu conteúdo diretamente no ecrã, torne-a um filho de um "
-"Control de modo a que obtenha um tamanho. Caso contrário, torne-a um "
-"RenderTarget e atribua a sua textura interna a outro nó para visualizar."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25317,6 +25360,15 @@ msgstr ""
"dimensões para renderizar."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 230c927086..41301db983 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -523,6 +523,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Comando"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Físico)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5654,6 +5659,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Seleção Do GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18844,6 +18854,11 @@ msgstr "O pacote deve ter pelo menos um separador '.'."
#: platform/android/export/export_plugin.cpp
#, fuzzy
+msgid "Custom Build"
+msgstr "Usar Diretório de Usuário Personalizado"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid "Use Custom Build"
msgstr "Usar Diretório de Usuário Personalizado"
@@ -18852,6 +18867,15 @@ msgstr "Usar Diretório de Usuário Personalizado"
msgid "Export Format"
msgstr "Caminho de Exportação"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "SDK Mínimo"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "FPS alvo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18895,15 +18919,6 @@ msgstr "Inspecionar a Instância Anterior"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "SDK Mínimo"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "FPS alvo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19155,14 +19170,16 @@ msgstr ""
"utilizar plugins."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Hand Tracking\" só é válido quando o \"Xr Mode\" é \"Oculus Mobile VR\"."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Passthrough\" só é válido quando o \"Xr Mode\" é \"Oculus Mobile VR\"."
@@ -19173,22 +19190,45 @@ msgstr ""
"habilitado."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Exportar AAB\" só é válido quando \"Usar Compilação Customizada\" está "
"habilitado."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Exportar AAB\" só é válido quando \"Usar Compilação Customizada\" está "
"habilitado."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"Versão do \"Target Sdk\" precisa ser igual ou maior que a versão do \"Min "
"Sdk\"."
@@ -20848,7 +20888,7 @@ msgstr "Ampliar"
msgid "Custom Viewport"
msgstr "1 Viewport"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21605,6 +21645,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "VInculamento"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Distância do Caminho U"
@@ -21613,6 +21658,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "Distância Máxima do Caminho"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avançado"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Habilitar"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21629,15 +21688,6 @@ msgstr "Inverter Horizontalmente"
msgid "Max Speed"
msgstr "Velocidade Máxima"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr "Distância Máxima do Caminho"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Habilitar"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25011,6 +25061,11 @@ msgstr "Pasta:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Selecionar Apenas"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Habilitar"
@@ -25420,19 +25475,6 @@ msgstr "Caminho de Exportação"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Este viewport não está definido como destino de renderização. Se você "
-"pretende que ele mostre seu conteúdo diretamente na tela, faça-o filho de um "
-"nó de Controle para que ele possa ter um tamanho. Caso contrário, defina-o "
-"como destino de renderização e atribua sua textura interna a algum nó para "
-"exibir."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25440,6 +25482,15 @@ msgstr ""
"dimensões para renderizar algo."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index ddc340697c..cdd11f3980 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -418,6 +418,11 @@ msgstr ""
msgid "Command"
msgstr "Comunitate"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Cadru Fizic %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5619,6 +5624,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Toată selecția"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18991,6 +19001,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Creează Nod"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18999,6 +19014,16 @@ msgstr ""
msgid "Export Format"
msgstr "Exportă Proiectul"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Dimensiunea Conturului:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Suprafață Țintă:"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19037,16 +19062,6 @@ msgstr "Fila anterioară"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Dimensiunea Conturului:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Suprafață Țintă:"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19292,12 +19307,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19306,17 +19321,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20968,7 +21003,7 @@ msgstr "Apropiere"
msgid "Custom Viewport"
msgstr "Arată Fereastra de Lucru"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21697,6 +21732,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Rotație aleatorie:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Alege o Scenă Principală"
@@ -21705,29 +21745,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avansate"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Activați"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Activați"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25004,6 +25049,11 @@ msgstr "Folderul:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Numai Selecția"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Activați"
@@ -25406,16 +25456,17 @@ msgstr "Exportă Proiectul"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 755683fdf0..84762459c8 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -115,13 +115,15 @@
# Deleted User <noreply+44465@weblate.org>, 2022.
# Bozhko Artyom Dmitrievich <jek_sun@mail.ru>, 2022.
# FuzzMix <fmwolfiechad@gmail.com>, 2022.
+# Jasuse <jasusemaele@gmail.com>, 2022.
+# Vadim Mitroshkin <Vadim7540@yandex.ru>, 2022.
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: 2022-06-12 13:19+0000\n"
-"Last-Translator: FuzzMix <fmwolfiechad@gmail.com>\n"
+"PO-Revision-Date: 2022-07-03 00:44+0000\n"
+"Last-Translator: Vadim Mitroshkin <Vadim7540@yandex.ru>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -130,7 +132,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -469,14 +471,12 @@ msgid "Max Size (KB)"
msgstr "МакÑимальный размер (КБ)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Режим перемещениÑ"
+msgstr "Режим мыши"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Удалить вход"
+msgstr "ИÑпользовать накопленный ввод"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -503,6 +503,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (ФизичеÑкаÑ)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -2332,8 +2337,9 @@ msgid "Fix Dependencies"
msgstr "ИÑправить завиÑимоÑти"
#: editor/dependency_editor.cpp
+#, fuzzy
msgid "Errors loading!"
-msgstr "Ошибки загрузки!"
+msgstr "Ошибки загружаютÑÑ!"
#: editor/dependency_editor.cpp
msgid "Permanently delete %d item(s)? (No undo!)"
@@ -5588,6 +5594,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "ÐÐ°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ Ð¿Ð¾ иÑтории дополнительными кнопками мыши"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Выделение Ñетки"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Внешний вид"
@@ -9530,7 +9541,7 @@ msgstr "Иконка"
#: editor/plugins/item_list_editor_plugin.cpp
msgid "ID"
-msgstr ""
+msgstr "Идентификатор"
#: editor/plugins/item_list_editor_plugin.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -17055,7 +17066,7 @@ msgstr "Скин Godot"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Img"
-msgstr ""
+msgstr "РаÑÑеÑнное изображение"
#: modules/gltf/gltf_spec_gloss.cpp
msgid "Diffuse Factor"
@@ -18486,6 +18497,11 @@ msgstr "Пакет должен иметь Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один раздели
#: platform/android/export/export_plugin.cpp
#, fuzzy
+msgid "Custom Build"
+msgstr "ИÑпользовать ÑобÑтвенную директорию данных пользователÑ"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid "Use Custom Build"
msgstr "ИÑпользовать ÑобÑтвенную директорию данных пользователÑ"
@@ -18494,6 +18510,16 @@ msgstr "ИÑпользовать ÑобÑтвенную директорию дÐ
msgid "Export Format"
msgstr "Путь ÑкÑпорта"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Минимальный размер"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Целевой FPS"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18537,16 +18563,6 @@ msgstr "ОÑмотреть предыдущий ÑкземплÑÑ€"
msgid "Code"
msgstr "Код"
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Минимальный размер"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Целевой FPS"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18800,15 +18816,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "«Use Custom Build» должен быть включен Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð¾Ð²."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"«Hand Tracking» дейÑтвителен только тогда, когда «Xr Mode» уÑтановлен в "
"«Oculus Mobile VrApi» или «OpenXR»."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"«Passthrough» дейÑтвителен только тогда, когда «Xr Mode» уÑтановлен в "
"«OpenXR»."
@@ -18820,22 +18838,45 @@ msgstr ""
"пользовательÑкую Ñборку»."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Изменение «Min Sdk» дейÑтвительно только еÑли включён параметр «ИÑпользовать "
"пользовательÑкую Ñборку»."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Изменение «Target Sdk» дейÑтвительно только еÑли включён параметр "
"«ИÑпользовать пользовательÑкую Ñборку»."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr "ВерÑÐ¸Ñ Â«Target Sdk» должна быть больше или равна верÑии «Min Sdk»."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20543,7 +20584,7 @@ msgstr "Приблизить"
msgid "Custom Viewport"
msgstr "1 Окно"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21293,6 +21334,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ПривÑзка"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "РаÑÑтоÑние пути U"
@@ -21301,6 +21347,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "МакÑимальное раÑÑтоÑние пути"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Дополнительно"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Включить"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21317,16 +21378,6 @@ msgstr "Перевернуть по горизонтали"
msgid "Max Speed"
msgstr "ÐœÐ°ÐºÑ ÑкороÑть"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "МакÑимальное раÑÑтоÑние пути"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Включить"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -24704,6 +24755,11 @@ msgstr "ПолоÑа ÑворачиваниÑ"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Только выделенное"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Включить"
@@ -25105,19 +25161,6 @@ msgstr "Путь ÑкÑпорта"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Этот viewport не уÑтановлен в качеÑтве цели рендеринга. ЕÑли вы ÑобираетеÑÑŒ "
-"иÑпользовать его Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñодержимого прÑмо на Ñкран, то Ñделайте её "
-"потомком Control'а, чтобы он мог получить размер. Ð’ противном Ñлучае, "
-"Ñделайте его целью рендеринга и назначьте его внутреннюю текÑтуру какому-"
-"либо узлу Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25125,6 +25168,15 @@ msgstr ""
"измерениÑÑ…, чтобы отобразить что-либо."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
@@ -26894,7 +26946,7 @@ msgstr "Передвинуть точки"
#: scene/resources/packed_scene.cpp
msgid "Bundled"
-msgstr ""
+msgstr "Вложенный"
#: scene/resources/particles_material.cpp
msgid "Trail"
@@ -27947,12 +27999,12 @@ msgstr "СовмеÑтимоÑть"
#: servers/visual_server.cpp
msgid "Disable Half Float"
-msgstr ""
+msgstr "Выключить вещеÑтвенные чиÑла половинной точноÑти"
#: servers/visual_server.cpp
#, fuzzy
msgid "Enable High Float"
-msgstr "Включить приоритет"
+msgstr "Включить вещеÑтвенные чиÑла повышенной точноÑти"
#: servers/visual_server.cpp
msgid "Precision"
@@ -27967,13 +28019,12 @@ msgid "UV Contract Amount"
msgstr ""
#: servers/visual_server.cpp
-#, fuzzy
msgid "Use Simple PVS"
-msgstr "ИÑпользовать привÑзку маÑштабированиÑ"
+msgstr "ИÑпользовать проÑтой PVS"
#: servers/visual_server.cpp
msgid "PVS Logging"
-msgstr ""
+msgstr "ВеÑти запиÑÑŒ PVS"
#: servers/visual_server.cpp
msgid "Use Signals"
@@ -28003,17 +28054,17 @@ msgid "Max Active Polygons"
msgstr "МакÑимальное количеÑтво активных полигонов"
#: servers/visual_server.cpp
-#, fuzzy
msgid "Shader Compilation Mode"
-msgstr "Режим интерполÑции"
+msgstr "Режим компилÑции шейдеров"
#: servers/visual_server.cpp
msgid "Max Simultaneous Compiles"
-msgstr ""
+msgstr "МакÑимальное количеÑтво одновременных компилÑций"
#: servers/visual_server.cpp
+#, fuzzy
msgid "Log Active Async Compiles Count"
-msgstr ""
+msgstr "РегиÑтрировать количеÑтво активных аÑинхронных компилÑций"
#: servers/visual_server.cpp
msgid "Shader Cache Size (MB)"
diff --git a/editor/translations/si.po b/editor/translations/si.po
index 2e5042392f..ae1abeaa5a 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -398,6 +398,10 @@ msgstr ""
msgid "Command"
msgstr ""
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5333,6 +5337,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17988,6 +17996,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "යතුරු පිටපත් කරන්න"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17996,6 +18009,15 @@ msgstr ""
msgid "Export Format"
msgstr "Anim පරිවර්තනය වෙනස් කරන්න"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "යතුරු මක෠දමන්න"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18032,15 +18054,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "යතුරු මක෠දමන්න"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18266,12 +18279,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18280,17 +18293,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19828,7 +19861,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20515,6 +20548,10 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Pathfinding"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20523,29 +20560,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "සමතුලිතයි"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "මෙම ලුහුබදින්න෠ඉවත් කරන්න."
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "මෙම ලුහුබදින්න෠ඉවත් කරන්න."
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23611,6 +23653,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23981,16 +24027,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index 9e18f67b73..6e20ee48da 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -431,6 +431,11 @@ msgstr ""
msgid "Command"
msgstr "Komunita"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fyzická Snímka %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5644,6 +5649,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Všetky vybrané"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18915,6 +18925,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Vložiť"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18923,6 +18938,16 @@ msgstr ""
msgid "Export Format"
msgstr "Konštanty:"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Veľkosť: "
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Vytvoriť Node"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18961,16 +18986,6 @@ msgstr "Minulá karta"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Veľkosť: "
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Vytvoriť Node"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19216,12 +19231,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19230,17 +19245,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20891,7 +20926,7 @@ msgstr "Priblížiť"
msgid "Custom Viewport"
msgstr "Zobraziť Výrez"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21627,6 +21662,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Prilepiť Animáciu"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Vyberte hlavnú scénu"
@@ -21635,29 +21675,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "PokroÄilé"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Povoliť"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Povoliť"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24931,6 +24976,11 @@ msgstr "PrieÄinok:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Iba Výber"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Povoliť"
@@ -25331,16 +25381,17 @@ msgstr "Zamerať Cestu"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index b796c872f7..43eb784a39 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -404,6 +404,11 @@ msgstr ""
msgid "Command"
msgstr "Skupnost"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fizikalni Okvir %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5715,6 +5720,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Izbriši Izbor"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19206,6 +19216,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Gradnik Prehod"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19214,6 +19229,16 @@ msgstr ""
msgid "Export Format"
msgstr "Izvozi Projekt"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Zaženi Skripto"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Gradnik ÄŒasovnoMerilo"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19253,16 +19278,6 @@ msgstr "Prejšnji zavihek"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Zaženi Skripto"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Gradnik ÄŒasovnoMerilo"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19509,12 +19524,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19523,17 +19538,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21190,7 +21225,7 @@ msgstr "Približaj"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21922,6 +21957,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Prilepi animacijo"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Izberi Glavno Sceno"
@@ -21930,29 +21970,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Možnosti pripenjanja"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "OmogoÄi"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "OmogoÄi"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25228,6 +25273,11 @@ msgstr "Ustvarite Mapo"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Samo Izbira"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "OmogoÄi"
@@ -25624,16 +25674,17 @@ msgstr "Izvozi Projekt"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index ae64fa2e6f..b11dc2f46f 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -415,6 +415,11 @@ msgstr ""
msgid "Command"
msgstr "Komuniteti"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Hapi i Fizikës %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5651,6 +5656,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Fshi të Selektuarat"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18698,6 +18708,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Dyfisho Nyjet"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18706,6 +18721,16 @@ msgstr ""
msgid "Export Format"
msgstr "Konstantet"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Madhësia: "
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Fshi Nyjen"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18744,16 +18769,6 @@ msgstr "Tabi i mëparshëm"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Madhësia: "
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Fshi Nyjen"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18998,12 +19013,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19012,17 +19027,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20654,7 +20689,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr "Zgjidh një 'Viewport'"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21359,6 +21394,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Konstantet"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Zgjidh një Skenë Kryesore"
@@ -21367,29 +21407,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "I Balancuar"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Lejo"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Lejo"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24550,6 +24595,11 @@ msgstr "Folderi:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Zgjidh Këtë Folder"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Lejo"
@@ -24941,16 +24991,17 @@ msgstr "Fokuso Rrugën"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index 89a0067fe9..e4a0475e3f 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -431,6 +431,11 @@ msgstr ""
msgid "Command"
msgstr "Заједница"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Слика физике %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5964,6 +5969,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "МапаМреже ИÑпуни Одабрано"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -20554,6 +20564,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Паковање мора имати бар један '.' раздвојник."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Ðаправи чвор"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -20562,6 +20577,16 @@ msgstr ""
msgid "Export Format"
msgstr "Извези пројекат"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Величина ивице:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Мета"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -20604,16 +20629,6 @@ msgstr "ИÑтражи Претходну ИнÑтанцу"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Величина ивице:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Мета"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -20876,12 +20891,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -20890,17 +20905,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -22599,7 +22634,7 @@ msgstr "Увеличај"
msgid "Custom Viewport"
msgstr "1 прозор"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -23374,6 +23409,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Спојеви"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Одабери ОдÑтојање:"
@@ -23382,6 +23422,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Одабери ОдÑтојање:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "ПоÑтавке залепљавања"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Укључи"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -23399,16 +23454,6 @@ msgstr "Обрни Хоризонтално"
msgid "Max Speed"
msgstr "Брзина (FPS):"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Одабери ОдÑтојање:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Укључи"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -26884,6 +26929,11 @@ msgstr "ПреÑавији линију"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Само одабрано"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Укључи"
@@ -27294,24 +27344,20 @@ msgstr "Извези пројекат"
#: scene/main/viewport.cpp
#, fuzzy
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Овај viewport није поÑтављен као мета за иÑцртавање. Ðко намераваш да "
-"прикаже Ñадржај директно на екран, учини га дететом Контроле да може да "
-"добави величину. У Ñупротном, учини га МетомИÑцртавања и додели његову "
-"унутрашњу текÑтуру неком чвору за приказ."
-
-#: 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 да би Ñе нешто иÑцртало."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 844e918f2d..9bbc31e19a 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -406,6 +406,11 @@ msgstr ""
msgid "Command"
msgstr "Zajednica"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Filtriraj signale"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5350,6 +5355,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Sve sekcije"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18053,6 +18063,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Animacija Uduplaj KljuÄeve"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18061,6 +18076,15 @@ msgstr ""
msgid "Export Format"
msgstr "Homogenost Boje."
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Ukloni ÄŒvor"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18097,15 +18121,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Ukloni ÄŒvor"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -18336,12 +18351,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18350,17 +18365,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19919,7 +19954,7 @@ msgstr "UveliÄaj"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20619,6 +20654,11 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Pathfinding"
+msgstr "Kontanta"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20627,29 +20667,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Napredno"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Filtriraj signale"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Filtriraj signale"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -23771,6 +23816,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Samo Obeleženo"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Filtriraj signale"
@@ -24147,16 +24197,17 @@ msgstr "Putanja"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index 61e607d63d..010299e2cf 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -442,6 +442,11 @@ msgstr ""
msgid "Command"
msgstr "Gemenskap"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Fysik Bildruta %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5660,6 +5665,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Alla urval"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18984,6 +18994,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Klipp ut Noder"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18992,6 +19007,16 @@ msgstr ""
msgid "Export Format"
msgstr "Exportera Projekt"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Storlek:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Byt Förälder-Node"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19030,16 +19055,6 @@ msgstr "Föregående flik"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Storlek:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Byt Förälder-Node"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19284,12 +19299,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19298,17 +19313,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20964,7 +20999,7 @@ msgstr "Zooma In"
msgid "Custom Viewport"
msgstr "Vy underifrån"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21696,6 +21731,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Slumpmässig Rotation:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Välj en Huvudscen"
@@ -21704,29 +21744,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "Avancerad"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Aktivera"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Aktivera"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25008,6 +25053,11 @@ msgstr "Mapp:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Endast Urval"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Aktivera"
@@ -25405,16 +25455,17 @@ msgstr "Exportera Projekt"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/te.po b/editor/translations/te.po
index 431febd63c..9e49f9dcc5 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -388,6 +388,10 @@ msgstr ""
msgid "Command"
msgstr "సంఘం"
+#: core/os/input_event.cpp
+msgid "Physical"
+msgstr ""
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5259,6 +5263,10 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+msgid "Drag And Drop Selection"
+msgstr ""
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -17717,6 +17725,10 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+msgid "Custom Build"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -17724,6 +17736,15 @@ msgstr ""
msgid "Export Format"
msgstr ""
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "నోడà±"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -17760,15 +17781,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr ""
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "నోడà±"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr ""
@@ -17988,12 +18000,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18002,17 +18014,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19527,7 +19559,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20196,6 +20228,11 @@ msgid ""
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Pathfinding"
+msgstr "à°¸à±à°¥à°¿à°°à°¾à°‚కాలà±"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
msgstr ""
@@ -20204,27 +20241,31 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
+msgid "Avoidance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+msgid "Avoidance Enabled"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
+msgid "Time Horizon"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Max Speed"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp
@@ -23184,6 +23225,10 @@ msgid "Fold Gutter"
msgstr ""
#: scene/gui/text_edit.cpp
+msgid "Drag And Drop Selection Enabled"
+msgstr ""
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr ""
@@ -23540,16 +23585,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/th.po b/editor/translations/th.po
index df7f3a8c04..1a6a4b71be 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -438,6 +438,11 @@ msgstr ""
msgid "Command"
msgstr "ชุมชน"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "% ของเฟรมฟิสิà¸à¸ªà¹Œ"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5639,6 +5644,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "เติมที่เลือà¸à¹ƒà¸™ GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18936,6 +18946,11 @@ msgid "The package must have at least one '.' separator."
msgstr "à¹à¸žà¹‡à¸„เà¸à¸ˆà¸ˆà¸³à¹€à¸›à¹‡à¸™à¸•้องมี '.' อย่างน้อยหนึ่งตัว"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ตัดโหนด"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18944,6 +18959,16 @@ msgstr ""
msgid "Export Format"
msgstr "ไดเรà¸à¸—อรีส่งออà¸"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "ขนาดเส้นรอบรูป:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "เป้าหมาย"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18986,16 +19011,6 @@ msgstr "ตรวจสอบอินสà¹à¸•นซ์à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "ขนาดเส้นรอบรูป:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "เป้าหมาย"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19242,13 +19257,13 @@ msgstr "\"Use Custom Build\" จำเป็นต้องเปิดà¸à¸²à¸£
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr "\"Hand Tracking\" จะสามารถใช้ได้เมื่อ \"Xr Mode\" เป็น \"Oculus Mobile VR\""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"Hand Tracking\" จะสามารถใช้ได้เมื่อ \"Xr Mode\" เป็น \"Oculus Mobile VR\""
#: platform/android/export/export_plugin.cpp
@@ -19258,18 +19273,38 @@ msgstr "\"Export AAB\" จะใช้ได้เฉพาะเมื่อเ
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\" จะใช้ได้เฉพาะเมื่อเปิดใช้งาน \"Use Custom Build\""
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "\"Export AAB\" จะใช้ได้เฉพาะเมื่อเปิดใช้งาน \"Use Custom Build\""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20946,7 +20981,7 @@ msgstr "ขยาย"
msgid "Custom Viewport"
msgstr "1 วิวพอร์ต"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21707,6 +21742,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ปุ่มลัด"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "ระยะà¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸:"
@@ -21715,6 +21755,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "ระยะà¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "ขั้นสูง"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "เปิด"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21732,16 +21787,6 @@ msgstr "พลิà¸à¹à¸™à¸§à¸™à¸­à¸™"
msgid "Max Speed"
msgstr "ความเร็ว:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "ระยะà¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "เปิด"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -25117,6 +25162,11 @@ msgstr "โฟลเดอร์:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "เฉพาะที่à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¸·à¸­à¸"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "เปิด"
@@ -25523,17 +25573,6 @@ msgid "Viewport Path"
msgstr "ไดเรà¸à¸—อรีส่งออà¸"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Viewport นี้ไม่ได้เป็น render target ถ้าท่านต้องà¸à¸²à¸£à¹à¸ªà¸”งผลบนหน้าจอโดยตรง "
-"ให้à¹à¸à¹‰à¹„ขโหนดนี้ให้เป็นโหนดลูà¸à¸‚อง Control à¹à¸•่ถ้าไม่ ให้ปรับเป็น render target à¹à¸¥à¸°à¸™à¸³à¹„ปใช้เป็น "
-"texture ของโหนดอื่น"
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25541,6 +25580,15 @@ msgid ""
msgstr "ขนาดวิวพอร์ตจะต้องมาà¸à¸à¸§à¹ˆà¸² 0 เพื่อที่จะเรนเดอร์ได้"
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/tl.po b/editor/translations/tl.po
index f67f19ad11..d5a5d52332 100644
--- a/editor/translations/tl.po
+++ b/editor/translations/tl.po
@@ -415,6 +415,11 @@ msgstr ""
msgid "Command"
msgstr "Pamayanan"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Paganahin"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5453,6 +5458,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Kopyahin Ang Pinagpipilian"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18258,6 +18268,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Kopyahin ang mga Node"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18266,6 +18281,16 @@ msgstr ""
msgid "Export Format"
msgstr "Iluwas ang Library"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Pangunahing Skrip:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Pinagtututukan"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18304,16 +18329,6 @@ msgstr "Nakaraang tab"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Pangunahing Skrip:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Pinagtututukan"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18552,12 +18567,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18566,17 +18581,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20201,7 +20236,7 @@ msgstr "Palakihin Ang Tanaw"
msgid "Custom Viewport"
msgstr "1 Tinginan"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20918,6 +20953,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Constant"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Pumili ng Pangunahing Eksena"
@@ -20926,6 +20966,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Paganahin"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Paganahin"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -20942,15 +20996,6 @@ msgstr ""
msgid "Max Speed"
msgstr "Bilis:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr ""
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Paganahin"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24179,6 +24224,11 @@ msgstr "Folder:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Napili lang"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Paganahin"
@@ -24570,14 +24620,6 @@ msgstr "1 Tinginan"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -24585,6 +24627,15 @@ msgstr ""
"alinman."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 89854afb02..1e4ab521bf 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -73,13 +73,14 @@
# inci <incialien@gmail.com>, 2022.
# Ramazan Aslan <legendraslan@gmail.com>, 2022.
# paledega <paledega@yandex.ru>, 2022.
+# Yekez <yasintonge@gmail.com>, 2022.
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: 2022-06-26 16:16+0000\n"
-"Last-Translator: paledega <paledega@yandex.ru>\n"
+"PO-Revision-Date: 2022-07-03 00:44+0000\n"
+"Last-Translator: Yekez <yasintonge@gmail.com>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/"
"godot/tr/>\n"
"Language: tr\n"
@@ -91,7 +92,7 @@ msgstr ""
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
-msgstr "Tablet Sürücüsü"
+msgstr "Tablet Sürücü"
#: core/bind/core_bind.cpp
msgid "Clipboard"
@@ -99,7 +100,7 @@ msgstr "Pano"
#: core/bind/core_bind.cpp
msgid "Current Screen"
-msgstr "Åžu anki ekran"
+msgstr "Åžu anki Ekran"
#: core/bind/core_bind.cpp
msgid "Exit Code"
@@ -107,7 +108,7 @@ msgstr "Çıkış Kodu"
#: core/bind/core_bind.cpp
msgid "V-Sync Enabled"
-msgstr "V-Sync EtkinleÅŸtirildi"
+msgstr "V-Sync Etkin"
#: core/bind/core_bind.cpp main/main.cpp
msgid "V-Sync Via Compositor"
@@ -461,6 +462,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Komut"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (Fiziksel)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5643,6 +5649,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap Seçimi"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18860,6 +18871,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Paket en azından bir tane '.' ayıracına sahip olmalıdır."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ÖzelSınıf"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18868,6 +18884,16 @@ msgstr ""
msgid "Export Format"
msgstr "Dışa aktarım Yolu"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Kontur Boyutu:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "Hedef"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18911,16 +18937,6 @@ msgstr "Önceki Örneği İncele"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Kontur Boyutu:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "Hedef"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19170,15 +19186,17 @@ msgstr ""
"Eklentileri kullanabilmek için \"Özel Derleme Kullan\" seçeneği aktif olmalı."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"El Takibi (Hand Tracking)\" sadece \"Xr Modu\" \"Oculus Mobile VR\" ya da "
"\"OpenXR\" olduğunda geçerlidir."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "\"İçinden Geçme\" sadece \"Xr Mod\" \"OpenXR\" ise geçerlidir."
#: platform/android/export/export_plugin.cpp
@@ -19188,22 +19206,45 @@ msgstr ""
"geçerlidir."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Min Sdk\" değiştirilmesi sadece \"Özel Yapı\" etkinleştirildiğinde "
"geçerlidir."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Target Sdk\" değiştirilmesi sadece \"Özel Yapı\" etkinleştirildiğinde "
"geçerlidir."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
"\"Target Sdk\" sürümü \"Min Sdk\" sürümünden daha büyük veya eşit olmalıdır."
@@ -20894,7 +20935,7 @@ msgstr "Yaklaştır"
msgid "Custom Viewport"
msgstr "1 Görüntü Kapısı"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21667,6 +21708,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Bağlayıcı"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Uzaklık Seç:"
@@ -21675,6 +21721,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "Uzaklık Seç:"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "GeliÅŸmiÅŸ"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Etkin"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21692,16 +21753,6 @@ msgstr "Yatay Yansıt"
msgid "Max Speed"
msgstr "Hız:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "Uzaklık Seç:"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Etkin"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -25148,6 +25199,11 @@ msgstr "Dosya:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Yalnızca Seçim"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Etkin"
@@ -25559,18 +25615,6 @@ msgstr "Dışa aktarım Yolu"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Bu görüntükapısı bir işleyici hedefi olarak ayarlanmamış. Eğer bunu doğrudan "
-"ekran içeriğini görüntülemek için düşünüyorsanız, bir Control'ün çocuğu "
-"yapın böylece bir boyut elde edebilir. Aksi takdirde, Görüntüleme için bunu "
-"bir RenderTarget yap ve dahili dokusunu herhangi bir düğüme ata."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -25578,6 +25622,15 @@ msgstr ""
"pikselden büyük ya da buna eşit olmalıdır."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 719dc29d7a..4d22a47dea 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -23,13 +23,14 @@
# Wald Sin <naaveranos@gmail.com>, 2022.
# Гліб Соколов <ramithes@i.ua>, 2022.
# Max Donchenko <maxx.donchenko@gmail.com>, 2022.
+# Artem <artem@molotov.work>, 2022.
msgid ""
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: 2022-06-12 13:19+0000\n"
-"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"PO-Revision-Date: 2022-07-03 00:44+0000\n"
+"Last-Translator: Artem <artem@molotov.work>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
"Language: uk\n"
@@ -38,7 +39,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.13-dev\n"
+"X-Generator: Weblate 4.13.1-dev\n"
#: core/bind/core_bind.cpp main/main.cpp
msgid "Tablet Driver"
@@ -378,14 +379,12 @@ msgid "Max Size (KB)"
msgstr "МакÑ. розмір (кБ)"
#: core/os/input.cpp
-#, fuzzy
msgid "Mouse Mode"
-msgstr "Режим переміщеннÑ"
+msgstr "Режим миші"
#: core/os/input.cpp
-#, fuzzy
msgid "Use Accumulated Input"
-msgstr "Видалити введеннÑ"
+msgstr "ВикориÑтати накопичувальне введеннÑ"
#: core/os/input_event.cpp editor/project_settings_editor.cpp
#: servers/audio_server.cpp
@@ -412,6 +411,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Команда"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (фізичний)"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -662,14 +666,12 @@ msgid "Script Templates Search Path"
msgstr "ШлÑÑ… пошуку Ð´Ð»Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ñ–Ð² Ñкриптів"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Autoload On Startup"
-msgstr "Ðвтоматично завантажувати під Ñ‡Ð°Ñ Ð·Ð°Ð¿ÑƒÑку"
+msgstr "Ðвтоматичне Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñми під Ñ‡Ð°Ñ Ð·Ð°Ð¿ÑƒÑку"
#: core/project_settings.cpp
-#, fuzzy
msgid "Version Control Plugin Name"
-msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñми"
+msgstr "Ðазва додатка ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñми"
#: core/project_settings.cpp scene/2d/collision_object_2d.cpp
#: scene/3d/collision_object.cpp scene/gui/control.cpp
@@ -2186,7 +2188,7 @@ msgstr "Відкрити"
#: editor/dependency_editor.cpp
msgid "Owners of: %s (Total: %d)"
-msgstr ""
+msgstr "ВлаÑник: %s (Загалом: %d)"
#: editor/dependency_editor.cpp
msgid ""
@@ -2746,22 +2748,19 @@ msgstr "Оберіть"
#: editor/editor_export.cpp
msgid "Project export for platform:"
-msgstr ""
+msgstr "ЕкÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð¸:"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed with errors."
-msgstr "Повні шлÑхи до файлів"
+msgstr "Завершено з помилками."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Completed successfully."
-msgstr "Пакунок уÑпішно вÑтановлено!"
+msgstr "Завершено уÑпішно."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed."
-msgstr "Ðе вдалоÑÑ:"
+msgstr "Помилка."
#: editor/editor_export.cpp
msgid "Storing File:"
@@ -2776,29 +2775,24 @@ msgid "Packing"
msgstr "ПакуваннÑ"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save PCK"
-msgstr "Зберегти Ñк"
+msgstr "Зберегти PCK"
#: editor/editor_export.cpp
-#, fuzzy
msgid "Cannot create file \"%s\"."
-msgstr "Ðеможливо Ñтворити теку."
+msgstr "Ðе вдалоÑÑ Ñтворити файл «%s»."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to export project files."
-msgstr "Ðе вдалоÑÑ ÐµÐºÑпортувати файли проєкту"
+msgstr "Ðе вдалоÑÑ ÐµÐºÑпортувати файли проєкту."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Can't open file to read from path \"%s\"."
-msgstr "Ðеможливо відкрити файл Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу:"
+msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ файл Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ñ– шлÑху «%s»."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Save ZIP"
-msgstr "Зберегти Ñк"
+msgstr "Зберегти ZIP"
#: editor/editor_export.cpp
msgid ""
@@ -2918,30 +2912,25 @@ msgid "Custom release template not found."
msgstr "Ðетипового шаблону випуÑку не знайдено."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Prepare Template"
-msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°Ð¼Ð¸"
+msgstr "Приготувати шаблон"
#: editor/editor_export.cpp platform/osx/export/export.cpp
-#, fuzzy
msgid "The given export path doesn't exist."
-msgstr "Вказаного шлÑху Ð´Ð»Ñ ÐµÐºÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує:"
+msgstr "Вказаного шлÑху Ð´Ð»Ñ ÐµÐºÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує."
#: editor/editor_export.cpp platform/javascript/export/export.cpp
-#, fuzzy
msgid "Template file not found: \"%s\"."
-msgstr "Файл шаблону не знайдено:"
+msgstr "Ðе знайдено файла шаблона: «%s»."
#: editor/editor_export.cpp
-#, fuzzy
msgid "Failed to copy export template."
-msgstr "Ðеправильний шаблон екÑпорту:"
+msgstr "Ðе вдалоÑÑ Ñкопіювати шаблон екÑпортуваннÑ."
#: editor/editor_export.cpp platform/windows/export/export.cpp
#: platform/x11/export/export.cpp
-#, fuzzy
msgid "PCK Embedding"
-msgstr "ФаÑка"
+msgstr "Ð’Ð±ÑƒÐ´Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ PCK"
#: editor/editor_export.cpp
msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."
@@ -5216,9 +5205,8 @@ msgstr ""
"меню «ЕкÑпорт» або визначне наÑвний набір Ñк придатний до викориÑтаннÑ."
#: editor/editor_run_native.cpp
-#, fuzzy
msgid "Project Run"
-msgstr "Проєкт"
+msgstr "ЗапуÑк проєкту"
#: editor/editor_run_script.cpp
msgid "Write your logic in the _run() method."
@@ -5502,6 +5490,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "Додаткові кнопки миші Ð´Ð»Ñ Ð½Ð°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ñ— журналом"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Вибір GridMap"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "ВиглÑд"
@@ -7156,12 +7149,18 @@ msgid ""
"%s: Texture detected as used as a normal map in 3D. Enabling red-green "
"texture compression to reduce memory usage (blue channel is discarded)."
msgstr ""
+"%s: виÑвлено текÑтуру, Ñк викориÑтано Ñк нормальну карту у проÑторовій "
+"формі. Вмикаємо ÑтиÑÐºÐ°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾-зеленої текÑтури Ð´Ð»Ñ Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ ÑÐ¿Ð¾Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ "
+"пам'Ñті (канал Ñинього відкинуто)."
#: editor/import/resource_importer_texture.cpp
msgid ""
"%s: Texture detected as used in 3D. Enabling filter, repeat, mipmap "
"generation and VRAM texture compression."
msgstr ""
+"%s: виÑвлено, що текÑтуру викориÑтано у проÑторовій формі. Вмикаємо "
+"фільтруваннÑ, повтореннÑ, ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¼Ð½Ð¾Ð¶Ð¸Ð½Ð½Ð¾Ð³Ð¾ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° ÑтиÑÐºÐ°Ð½Ð½Ñ "
+"текÑтур у відеопам'Ñті."
#: editor/import/resource_importer_texture.cpp
msgid "2D, Detect 3D"
@@ -11504,9 +11503,8 @@ msgid "Invalid geometry, can't replace by mesh."
msgstr "Ðекоректна геометріÑ, неможливо замінити Ñіткою."
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Convert to MeshInstance2D"
-msgstr "Перетворити на Mesh2D"
+msgstr "Перетворити на MeshInstance2D"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Invalid geometry, can't create polygon."
@@ -12875,14 +12873,12 @@ msgid "Selected Collision"
msgstr "Позначене зіткненнÑ"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way"
-msgstr "Тільки виділити"
+msgstr "Позначене одноÑпрÑмоване зіткненнÑ"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Selected Collision One Way Margin"
-msgstr "Поле Ð·Ñ–Ñ‚ÐºÐ½ÐµÐ½Ð½Ñ BVH"
+msgstr "Поле позначеного одноÑпрÑмованого зіткненнÑ"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Selected Navigation"
@@ -14142,9 +14138,8 @@ msgid "Export templates for this platform are missing:"
msgstr "Ðемає шаблонів екÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— платформи:"
#: editor/project_export.cpp
-#, fuzzy
msgid "Project Export"
-msgstr "ЗаÑновники проєкту"
+msgstr "ЕкÑÐ¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ"
#: editor/project_export.cpp
msgid "Manage Export Templates"
@@ -16705,7 +16700,7 @@ msgstr "Копіювати вузол шлÑху"
#: modules/gdscript/gdscript.cpp modules/visual_script/visual_script.cpp
msgid "Max Call Stack"
-msgstr ""
+msgstr "МакÑимум Ñтеку викликів"
#: modules/gdscript/gdscript.cpp
msgid "Treat Warnings As Errors"
@@ -16815,11 +16810,11 @@ msgstr "КількіÑть розÑіюваннÑ"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Buffer View"
-msgstr ""
+msgstr "ПереглÑд буфера розріджених індекÑів"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Byte Offset"
-msgstr ""
+msgstr "Байтовий зÑув розріджених індекÑів"
#: modules/gltf/gltf_accessor.cpp
msgid "Sparse Indices Component Type"
@@ -18362,6 +18357,11 @@ msgid "The package must have at least one '.' separator."
msgstr "У назві пакунка має бути принаймні один роздільник «.»."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Ðетипова збірка"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "Ðетипова збірка"
@@ -18369,6 +18369,14 @@ msgstr "Ðетипова збірка"
msgid "Export Format"
msgstr "Формат екÑпортуваннÑ"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "Мін. SDK"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "SDK призначеннÑ"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18406,14 +18414,6 @@ msgstr "Вилучити попередньо вÑтановлене"
msgid "Code"
msgstr "Код"
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "Мін. SDK"
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr "SDK призначеннÑ"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr "Пакунок"
@@ -18651,15 +18651,17 @@ msgstr ""
"«ВикориÑтовувати нетипову збірку»."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"«СтеженнÑм за руками» можна ÑкориÑтатиÑÑ, лише Ñкщо «Режим Xr» дорівнює "
"«Oculus Mobile VR» або «OpenXR»."
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"«СтеженнÑм за руками» можна ÑкориÑтатиÑÑ, лише Ñкщо «Режим Xr» дорівнює "
"«OpenXR»."
@@ -18671,22 +18673,45 @@ msgstr ""
"нетипове збираннÑ»."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Пункт «Мін. SDK» Ñ” чинним, лише Ñкщо увімкнено «ВикориÑтовувати нетипове "
"збираннÑ»."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"Пункт «SDK цілі» Ñ” чинним, лише Ñкщо увімкнено «ВикориÑтовувати нетипове "
"збираннÑ»."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr "ВерÑÑ–Ñ Â«SDK цілі» має бути більшою або рівною за верÑÑ–ÑŽ «Мін. SDK»."
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -19029,7 +19054,7 @@ msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð¼Ñ–ÐºÑ€Ð¾Ñ„Ð¾Ð½Ð°"
#: platform/iphone/export/export.cpp
msgid "Photolibrary Usage Description"
-msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ фотографій"
+msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ Ñвітлин"
#: platform/iphone/export/export.cpp
msgid "iPhone 120 X 120"
@@ -19349,7 +19374,7 @@ msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ"
#: platform/osx/export/export.cpp
msgid "Photos Library Usage Description"
-msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ фотографій"
+msgstr "ÐžÐ¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð±Ñ–Ð±Ð»Ñ–Ð¾Ñ‚ÐµÐºÐ¸ Ñвітлин"
#: platform/osx/export/export.cpp
msgid "Desktop Folder Usage Description"
@@ -19430,7 +19455,7 @@ msgstr "Календарі"
#: platform/osx/export/export.cpp
msgid "Photos Library"
-msgstr "Бібліотека фотографій"
+msgstr "Бібліотека Ñвітлин"
#: platform/osx/export/export.cpp
msgid "Apple Events"
@@ -19815,7 +19840,7 @@ msgid ""
"Privacy: Photo library access is enabled, but usage description is not "
"specified."
msgstr ""
-"КонфіденційніÑть: увімкнено доÑтуп до бібліотеки фотографій, але Ð¾Ð¿Ð¸Ñ "
+"КонфіденційніÑть: увімкнено доÑтуп до бібліотеки Ñвітлин, але Ð¾Ð¿Ð¸Ñ "
"викориÑÑ‚Ð°Ð½Ð½Ñ Ð½Ðµ вказано."
#: platform/osx/export/export.cpp
@@ -20348,7 +20373,7 @@ msgstr "МаÑштаб"
msgid "Custom Viewport"
msgstr "1 панель переглÑду"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -21036,6 +21061,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Палітурка"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "U-відÑтань контуру"
@@ -21044,6 +21074,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "МакÑ. відÑтань контуру"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Додатково"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21059,15 +21103,6 @@ msgstr "Віддзеркалити горизонтально"
msgid "Max Speed"
msgstr "МакÑ. швидкіÑть"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr "МакÑ. відÑтань контуру"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
-
#: scene/2d/navigation_agent_2d.cpp
#, fuzzy
msgid ""
@@ -24180,6 +24215,11 @@ msgid "Fold Gutter"
msgstr "МіжÑтовпцевий проміжок згортаннÑ"
#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Увімкнено позначеннÑ"
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr "ÐŸÑ€Ð¸Ñ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
@@ -24538,18 +24578,6 @@ msgstr "ШлÑÑ… до панелі переглÑду"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"Ð¦Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ показу не Ñ” ціллю обробки зображеннÑ. Якщо ви хочете, щоб Ñ—Ñ— вміÑÑ‚ "
-"було безпоÑередньо показано на екрані, зробіть Ñ—Ñ— дочірньою Ð´Ð»Ñ Ð²ÑƒÐ·Ð»Ð° "
-"Control, щоб у неї був розмір. Крім того, можна зробити її RenderTarget і "
-"пов'Ñзати Ñ—Ñ— внутрішню текÑтуру з одним із вузлів Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ."
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
@@ -24557,6 +24585,15 @@ msgstr ""
"або рівним 2 пікÑелÑм в обох вимірах."
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr "ARVR"
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 76cd6b6495..e1bae41d6b 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -408,6 +408,11 @@ msgstr ""
msgid "Command"
msgstr "کمیونٹی"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "سب سکریپشن بنائیں"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5407,6 +5412,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr ".تمام کا انتخاب"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -18373,6 +18383,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "ایکشن منتقل کریں"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18381,6 +18396,16 @@ msgstr ""
msgid "Export Format"
msgstr "سب سکریپشن بنائیں"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "سب سکریپشن بنائیں"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr ".اینیمیشن کی کیز کو ڈیلیٹ کرو"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -18417,16 +18442,6 @@ msgstr ""
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "سب سکریپشن بنائیں"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr ".اینیمیشن کی کیز کو ڈیلیٹ کرو"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -18663,12 +18678,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -18677,17 +18692,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20272,7 +20307,7 @@ msgstr ""
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -20972,6 +21007,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "مستقل"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "ایک مینو منظر چنیں"
@@ -20980,29 +21020,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "سب سکریپشن بنائیں"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "سب سکریپشن بنائیں"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "سب سکریپشن بنائیں"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -24102,6 +24147,11 @@ msgstr ""
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr ".تمام کا انتخاب"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "سب سکریپشن بنائیں"
@@ -24481,16 +24531,17 @@ msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 2b4093cc17..c8eae36ad6 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -412,6 +412,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "Vật lí"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5492,6 +5497,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "Chá»n tất cả"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "Ngoại hình"
@@ -18786,6 +18796,11 @@ msgid "The package must have at least one '.' separator."
msgstr "Kí tự phân cách '.' phải xuất hiện ít nhất một lần trong tên gói."
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "Cắt các nút"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18794,6 +18809,16 @@ msgstr ""
msgid "Export Format"
msgstr "ÄÆ°á»ng dẫn xuất"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "Kích cỡ viá»n:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "BỠmặt mục tiêu:"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18836,16 +18861,6 @@ msgstr "Cửa sổ trước"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "Kích cỡ viá»n:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "BỠmặt mục tiêu:"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19092,7 +19107,7 @@ msgstr "\"Sá»­ dụng Bản dá»±ng tùy chỉnh\" phải được bật để sá
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"\"Theo dõi chuyển động tay\" chỉ dùng được khi \"Xr Mode\" là \"Oculus "
@@ -19100,7 +19115,7 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
"\"Theo dõi chuyển động tay\" chỉ dùng được khi \"Xr Mode\" là \"Oculus "
"Mobile VR\"."
@@ -19113,20 +19128,40 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Xuất AAB\" chỉ dùng được khi \"Sử dụng Bản dựng tùy chỉnh\" được bật."
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
#, fuzzy
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
"\"Xuất AAB\" chỉ dùng được khi \"Sử dụng Bản dựng tùy chỉnh\" được bật."
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20810,7 +20845,7 @@ msgstr "Phóng to"
msgid "Custom Viewport"
msgstr "1 Cổng xem"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21568,6 +21603,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "Äệm"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "Chá»n ô"
@@ -21576,6 +21616,20 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr ""
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "Nâng cao"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "Mở"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21593,15 +21647,6 @@ msgstr "Lật Ngang"
msgid "Max Speed"
msgstr "Tốc độ:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr ""
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "Mở"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24954,6 +24999,11 @@ msgstr "Thư mục:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "Chỉ chá»n"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "Mở"
@@ -25358,16 +25408,17 @@ msgstr "ÄÆ°á»ng dẫn xuất"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
+"The Viewport size must be greater than or equal to 2 pixels on both "
+"dimensions to render anything."
msgstr ""
#: scene/main/viewport.cpp
msgid ""
-"The Viewport size must be greater than or equal to 2 pixels on both "
-"dimensions to render anything."
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
msgstr ""
#: scene/main/viewport.cpp
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 4a15f6acf3..976fe38138 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -89,7 +89,7 @@ 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: 2022-06-20 06:44+0000\n"
+"PO-Revision-Date: 2022-06-30 16:42+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"
@@ -466,6 +466,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (物ç†ï¼‰"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5431,6 +5436,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "使用专门鼠标按键查看历å²"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "GridMap 选择"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外观"
@@ -18065,6 +18075,11 @@ msgid "The package must have at least one '.' separator."
msgstr "包必须至少有一个 “.†分隔符。"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "使用自定义构建"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr "使用自定义构建"
@@ -18072,6 +18087,14 @@ msgstr "使用自定义构建"
msgid "Export Format"
msgstr "导出格å¼"
+#: platform/android/export/export_plugin.cpp
+msgid "Min SDK"
+msgstr "æœ€å° SDK"
+
+#: platform/android/export/export_plugin.cpp
+msgid "Target SDK"
+msgstr "目标 SDK"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr "æž¶æž„"
@@ -18108,14 +18131,6 @@ msgstr "清除上次安装"
msgid "Code"
msgstr "代ç "
-#: platform/android/export/export_plugin.cpp
-msgid "Min SDK"
-msgstr "æœ€å° SDK"
-
-#: platform/android/export/export_plugin.cpp
-msgid "Target SDK"
-msgstr "目标 SDK"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
msgid "Package"
msgstr "包"
@@ -18337,14 +18352,14 @@ msgstr "å¿…é¡»å¯ç”¨ “使用自定义构建†æ‰èƒ½ä½¿ç”¨æ’件。"
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
-"“Hand Trackingâ€åªæœ‰åœ¨å½““Xr Modeâ€æ˜¯â€œOculus Mobile VrApiâ€æˆ–“OpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+"“Hand Trackingâ€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOculus Mobile VrApiâ€æˆ–“OpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚"
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
-msgstr "“Passthroughâ€åªæœ‰åœ¨å½““Xr Modeâ€æ˜¯â€œOpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
+msgstr "“Passthroughâ€åªæœ‰åœ¨å½““XR Modeâ€æ˜¯â€œOpenXRâ€æ—¶æ‰æœ‰æ•ˆã€‚"
#: platform/android/export/export_plugin.cpp
msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
@@ -18352,18 +18367,38 @@ msgstr "“Export AABâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
-msgstr "修改“Min Sdkâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr "修改“Min SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
-msgstr "修改“Target Sdkâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
-msgstr "“Target Sdkâ€ç‰ˆæœ¬å¿…须大于等于“Min Sdkâ€ç‰ˆæœ¬ã€‚"
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr "修改“Target SDKâ€åªæœ‰åœ¨å½“å¯ç”¨â€œUse Custom Buildâ€æ—¶æ‰æœ‰æ•ˆã€‚"
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
+msgstr "“Target SDKâ€ç‰ˆæœ¬å¿…须大于等于“Min SDKâ€ç‰ˆæœ¬ã€‚"
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
#: platform/windows/export/export.cpp
@@ -19894,7 +19929,7 @@ msgstr "缩放"
msgid "Custom Viewport"
msgstr "自定义视区"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
msgid "Process Mode"
@@ -20567,17 +20602,36 @@ msgid ""
"will be removed in a future version. Use 'Navigation2DServer.map_get_path()' "
"instead."
msgstr ""
+"“Navigation2Dâ€èŠ‚ç‚¹å’Œâ€œNavigation2D.get_simple_path()â€å·²åºŸå¼ƒï¼Œä¼šåœ¨å°†æ¥çš„版本中"
+"移除。请用“Navigation2DServer.map_get_path()â€æ›¿ä»£ã€‚"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "绑定"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Path Desired Distance"
-msgstr "目标期望è·ç¦»"
+msgstr "路径期望è·ç¦»"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Target Desired Distance"
msgstr "目标期望è·ç¦»"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Path Max Distance"
+msgstr "路径最大è·ç¦»"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "高级"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Avoidance Enabled"
+msgstr "å¯ç”¨é¿éšœ"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr "邻接è·ç¦»"
@@ -20593,14 +20647,6 @@ msgstr "时间下é™"
msgid "Max Speed"
msgstr "最大速度"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
-msgstr "路径最大è·ç¦»"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Avoidance Enabled"
-msgstr "å¯ç”¨é¿éšœ"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -21699,6 +21745,8 @@ msgid ""
"be removed in a future version. Use 'NavigationServer.map_get_path()' "
"instead."
msgstr ""
+"“Navigationâ€èŠ‚ç‚¹å’Œâ€œNavigation.get_simple_path()â€å·²åºŸå¼ƒï¼Œä¼šåœ¨å°†æ¥çš„版本中移"
+"除。请用“NavigationServer.map_get_path()â€æ›¿ä»£ã€‚"
#: scene/3d/navigation.cpp scene/resources/curve.cpp
msgid "Up Vector"
@@ -23603,6 +23651,11 @@ msgid "Fold Gutter"
msgstr "æŠ˜å æ "
#: scene/gui/text_edit.cpp
+#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "å¯ç”¨é€‰æ‹©"
+
+#: scene/gui/text_edit.cpp
msgid "Hiding Enabled"
msgstr "å¯ç”¨éšè—"
@@ -23959,22 +24012,20 @@ msgstr "Viewport 路径"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"这个视窗未被设置为渲染目标。如果你想让其直接在å±å¹•上显示内容,请使其æˆä¸º "
-"Control çš„å­èŠ‚ç‚¹ï¼Œè¿™æ ·ä¸€æ¥è¯¥ Viewport æ‰ä¼šæœ‰å¤§å°ã€‚å¦åˆ™è¯·ä¸ºå…¶è®¾ç½® "
-"RenderTarget 并分é…å…¶å†…éƒ¨çº¹ç†æ¥æ˜¾ç¤ºã€‚"
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr "Viewport 的宽高都大于等于 2 åƒç´ æ—¶æ‰èƒ½è¿›è¡Œæ¸²æŸ“。"
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr "ARVR"
@@ -25482,14 +25533,12 @@ msgid "Walkable Low Height Spans"
msgstr "å¯è¡Œèµ°ä½Žé«˜åº¦èŒƒå›´"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Baking AABB"
-msgstr "æ­£åœ¨ç”Ÿæˆ AABB"
+msgstr "烘焙 AABB"
#: scene/resources/navigation_mesh.cpp
-#, fuzzy
msgid "Baking AABB Offset"
-msgstr "基础åç§»"
+msgstr "烘焙 AABB åç§»"
#: scene/resources/occluder_shape.cpp
msgid "Spheres"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index 114f6b0a45..201811d543 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -417,6 +417,11 @@ msgstr ""
msgid "Command"
msgstr "社群"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr "物ç†å¹€ %"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5663,6 +5668,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr ""
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "刪除é¸ä¸­æª”案"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr ""
@@ -19119,6 +19129,11 @@ msgid "The package must have at least one '.' separator."
msgstr ""
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "貼上"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -19127,6 +19142,16 @@ msgstr ""
msgid "Export Format"
msgstr "匯出"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "下一個腳本"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "目標"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
msgid "Architectures"
msgstr ""
@@ -19165,16 +19190,6 @@ msgstr "上一個tab"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "下一個腳本"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "目標"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19419,12 +19434,12 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr ""
#: platform/android/export/export_plugin.cpp
@@ -19433,17 +19448,37 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
msgstr ""
#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr ""
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr ""
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -21095,7 +21130,7 @@ msgstr "放大"
msgid "Custom Viewport"
msgstr ""
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21810,6 +21845,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "貼上動畫"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "鏿“‡ä¸»å ´æ™¯"
@@ -21818,29 +21858,34 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Neighbor Dist"
+msgid "Path Max Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Neighbors"
-msgstr ""
+#, fuzzy
+msgid "Avoidance"
+msgstr "進階"
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Time Horizon"
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "啟用"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+msgid "Neighbor Dist"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Max Speed"
+msgid "Max Neighbors"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-msgid "Path Max Distance"
+msgid "Time Horizon"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "啟用"
+msgid "Max Speed"
+msgstr ""
#: scene/2d/navigation_agent_2d.cpp
msgid ""
@@ -25061,6 +25106,11 @@ msgstr "資料夾:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "åªé™é¸ä¸­"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "啟用"
@@ -25454,14 +25504,6 @@ msgid "Viewport Path"
msgstr "匯出"
#: scene/main/viewport.cpp
-msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-
-#: scene/main/viewport.cpp
#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
@@ -25469,6 +25511,15 @@ msgid ""
msgstr "viewport大å°å¿…須大於ï¼ä»¥æ¸²æŸ“任何æ±è¥¿ã€‚"
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index bcf6650997..9021c16fc8 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -434,6 +434,11 @@ msgstr "Meta"
msgid "Command"
msgstr "Command"
+#: core/os/input_event.cpp
+#, fuzzy
+msgid "Physical"
+msgstr " (物ç†ï¼‰"
+
#: core/os/input_event.cpp scene/2d/touch_screen_button.cpp
#: scene/gui/base_button.cpp scene/gui/texture_button.cpp
#: scene/resources/default_theme/default_theme.cpp
@@ -5585,6 +5590,11 @@ msgid "Mouse Extra Buttons Navigate History"
msgstr "滑鼠é¡å¤–æŒ‰éµæ“作歷å²ç´€éŒ„"
#: editor/editor_settings.cpp
+#, fuzzy
+msgid "Drag And Drop Selection"
+msgstr "鏿“‡ç¶²æ ¼åœ°åœ–"
+
+#: editor/editor_settings.cpp
msgid "Appearance"
msgstr "外觀"
@@ -18704,6 +18714,11 @@ msgid "The package must have at least one '.' separator."
msgstr "套件必須至少有一個「.ã€åˆ†éš”字元。"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Custom Build"
+msgstr "剪下節點"
+
+#: platform/android/export/export_plugin.cpp
msgid "Use Custom Build"
msgstr ""
@@ -18712,6 +18727,16 @@ msgstr ""
msgid "Export Format"
msgstr "匯出路徑"
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Min SDK"
+msgstr "輪廓尺寸:"
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "Target SDK"
+msgstr "目標"
+
#: platform/android/export/export_plugin.cpp platform/iphone/export/export.cpp
#, fuzzy
msgid "Architectures"
@@ -18754,16 +18779,6 @@ msgstr "嵿Ÿ¥å‰ä¸€å€‹å¯¦é«”"
msgid "Code"
msgstr ""
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Min SDK"
-msgstr "輪廓尺寸:"
-
-#: platform/android/export/export_plugin.cpp
-#, fuzzy
-msgid "Target SDK"
-msgstr "目標"
-
#: platform/android/export/export_plugin.cpp platform/uwp/export/export.cpp
#, fuzzy
msgid "Package"
@@ -19003,15 +19018,17 @@ msgid "\"Use Custom Build\" must be enabled to use the plugins."
msgstr "「使用自定建置ã€å¿…須啟用以使用本外掛。"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VrApi\" "
+"\"Hand Tracking\" is only valid when \"XR Mode\" is \"Oculus Mobile VrApi\" "
"or \"OpenXR\"."
msgstr ""
"「Hand Trackingã€ï¼ˆæ‰‹éƒ¨è¿½è¹¤ï¼‰åƒ…å¯åœ¨ã€ŒXr Modeã€ï¼ˆXR 模å¼ï¼‰è¨­ç‚ºã€ŒOculus Mobile "
"VRã€æˆ–「OpenXRã€æ™‚å¯ç”¨ã€‚"
#: platform/android/export/export_plugin.cpp
-msgid "\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\"."
+#, fuzzy
+msgid "\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\"."
msgstr "「Passthroughã€åƒ…å¯åœ¨ã€ŒXr Modeã€ï¼ˆXR 模å¼ï¼‰è¨­ç‚ºã€ŒOpenXRã€æ™‚å¯ç”¨ã€‚"
#: platform/android/export/export_plugin.cpp
@@ -19019,18 +19036,41 @@ msgid "\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."
msgstr "「Export AABã€åƒ…於「Use Custom Buildã€å•Ÿç”¨æ™‚å¯ç”¨ã€‚"
#: platform/android/export/export_plugin.cpp
+#, fuzzy
msgid ""
-"Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."
+"\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "å°ã€ŒMin Sdkã€çš„修改僅在「Use Custom Buildã€å•Ÿç”¨æ™‚有效。"
#: platform/android/export/export_plugin.cpp
+msgid "\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
msgid ""
-"Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is "
-"enabled."
+"\"Min SDK\" cannot be lower than %d, which is the version needed by the "
+"Godot library."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid ""
+"\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled."
msgstr "å°ã€ŒTarget Sdkã€çš„修改僅於「Use Custom Buildã€å•Ÿç”¨æ™‚有效。"
#: platform/android/export/export_plugin.cpp
-msgid "\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."
+msgid ""
+"\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+msgid ""
+"\"Target SDK\" %d is higher than the default version %d. This may work, but "
+"wasn't tested and may be unstable."
+msgstr ""
+
+#: platform/android/export/export_plugin.cpp
+#, fuzzy
+msgid "\"Target SDK\" version must be greater or equal to \"Min SDK\" version."
msgstr "「Target Sdkã€ç‰ˆæœ¬å¿…須高於或于「Min Sdkã€ç‰ˆæœ¬ä¸€è‡´ã€‚"
#: platform/android/export/export_plugin.cpp platform/osx/export/export.cpp
@@ -20711,7 +20751,7 @@ msgstr "放大"
msgid "Custom Viewport"
msgstr "1 個檢視å€"
-#: scene/2d/camera_2d.cpp scene/3d/camera.cpp
+#: scene/2d/camera_2d.cpp scene/3d/camera.cpp scene/3d/interpolated_camera.cpp
#: scene/animation/animation_player.cpp scene/animation/animation_tree.cpp
#: scene/animation/animation_tree_player.cpp scene/main/timer.cpp
#, fuzzy
@@ -21472,6 +21512,11 @@ msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
#, fuzzy
+msgid "Pathfinding"
+msgstr "ç¶å®š"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
msgid "Path Desired Distance"
msgstr "鏿“‡è·é›¢ï¼š"
@@ -21480,6 +21525,21 @@ msgid "Target Desired Distance"
msgstr ""
#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Path Max Distance"
+msgstr "鏿“‡è·é›¢ï¼š"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance"
+msgstr "進階"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
+#, fuzzy
+msgid "Avoidance Enabled"
+msgstr "啟用"
+
+#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
msgid "Neighbor Dist"
msgstr ""
@@ -21497,16 +21557,6 @@ msgstr "水平翻轉"
msgid "Max Speed"
msgstr "速度:"
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Path Max Distance"
-msgstr "鏿“‡è·é›¢ï¼š"
-
-#: scene/2d/navigation_agent_2d.cpp scene/3d/navigation_agent.cpp
-#, fuzzy
-msgid "Avoidance Enabled"
-msgstr "啟用"
-
#: scene/2d/navigation_agent_2d.cpp
msgid ""
"The NavigationAgent2D can be used only under a Node2D inheriting parent node."
@@ -24903,6 +24953,11 @@ msgstr "資料夾:"
#: scene/gui/text_edit.cpp
#, fuzzy
+msgid "Drag And Drop Selection Enabled"
+msgstr "僅æœå°‹æ‰€é¸å€åŸŸ"
+
+#: scene/gui/text_edit.cpp
+#, fuzzy
msgid "Hiding Enabled"
msgstr "啟用"
@@ -25313,22 +25368,20 @@ msgstr "匯出路徑"
#: scene/main/viewport.cpp
msgid ""
-"This viewport is not set as render target. If you intend for it to display "
-"its contents directly to the screen, make it a child of a Control so it can "
-"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
-"texture to some node for display."
-msgstr ""
-"該 Viewport 尚未被設定為算繪目標。若你想直接將其內容顯示於畫é¢ä¸Šï¼Œè«‹å°‡å…¶è¨­ç‚º "
-"Control çš„å­ç¯€é»žä»¥è®“å…¶å–得大å°ã€‚å¦å‰‡è«‹å°‡å…¶è¨­ç‚º RenderTarget 並指派其內部紋ç†"
-"為其他節點以顯示。"
-
-#: scene/main/viewport.cpp
-msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr "Viewport長與寬必須皆大於或等於2åƒç´ æ‰å¯é€²è¡Œç®—繪。"
#: scene/main/viewport.cpp
+msgid ""
+"This Viewport has HDR enabled, but its Usage is set to 2D or 2D No-"
+"Sampling.\n"
+"HDR is only supported in Viewports that have their Usage set to 3D or 3D No-"
+"Effects.\n"
+"HDR will be disabled for this Viewport."
+msgstr ""
+
+#: scene/main/viewport.cpp
msgid "ARVR"
msgstr ""
diff --git a/main/main.cpp b/main/main.cpp
index 00b7483406..2bb67f17f1 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -621,11 +621,18 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
/* argument parsing and main creation */
List<String> args;
List<String> main_args;
+ List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args();
+ // Add command line arguments.
for (int i = 0; i < argc; i++) {
args.push_back(String::utf8(argv[i]));
}
+ // Add arguments received from macOS LaunchService (URL schemas, file associations).
+ for (const String &arg : platform_args) {
+ args.push_back(arg);
+ }
+
List<String>::Element *I = args.front();
while (I) {
@@ -691,12 +698,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help
show_help = true;
- exit_code = OK;
+ exit_code = ERR_HELP; // Hack to force an early exit in `main()` with a success code.
goto error;
} else if (I->get() == "--version") {
print_line(get_full_version_string());
- exit_code = OK;
+ exit_code = ERR_HELP; // Hack to force an early exit in `main()` with a success code.
goto error;
} else if (I->get() == "-v" || I->get() == "--verbose") { // verbose output
@@ -1460,11 +1467,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
/* Determine audio and video drivers */
// Display driver, e.g. X11, Wayland.
- // print_line("requested display driver : " + display_driver);
+ // Make sure that headless is the last one, which it is assumed to be by design.
+ DEV_ASSERT(String("headless") == DisplayServer::get_create_function_name(DisplayServer::get_create_function_count() - 1));
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
String name = DisplayServer::get_create_function_name(i);
- // print_line("\t" + itos(i) + " : " + name);
-
if (display_driver == name) {
display_driver_idx = i;
break;
@@ -1472,6 +1478,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
if (display_driver_idx < 0) {
+ // If the requested driver wasn't found, pick the first entry.
+ // If all else failed it would be the headless server.
display_driver_idx = 0;
}
@@ -1484,6 +1492,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
audio_driver = GLOBAL_GET("audio/driver/driver");
}
+ // Make sure that dummy is the last one, which it is assumed to be by design.
+ DEV_ASSERT(String("Dummy") == AudioDriverManager::get_driver(AudioDriverManager::get_driver_count() - 1)->get_name());
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) {
audio_driver_idx = i;
@@ -1492,7 +1502,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
if (audio_driver_idx < 0) {
- audio_driver_idx = 0; // 0 Is always available as the dummy driver (no sound)
+ // If the requested driver wasn't found, pick the first entry.
+ // If all else failed it would be the dummy driver (no sound).
+ audio_driver_idx = 0;
}
if (write_movie_path != String()) {
@@ -1685,10 +1697,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
Error err;
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err != OK || display_server == nullptr) {
- //ok i guess we can't use this display server, try other ones
- for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
+ // We can't use this display server, try other ones as fallback.
+ // Skip headless (always last registered) because that's not what users
+ // would expect if they didn't request it explicitly.
+ for (int i = 0; i < DisplayServer::get_create_function_count() - 1; i++) {
if (i == display_driver_idx) {
- continue; //don't try the same twice
+ continue; // Don't try the same twice.
}
display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_size, err);
if (err == OK && display_server != nullptr) {
@@ -2184,6 +2198,13 @@ bool Main::start() {
#endif
}
+ uint64_t minimum_time_msec = GLOBAL_DEF("application/boot_splash/minimum_display_time", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/minimum_display_time",
+ PropertyInfo(Variant::INT,
+ "application/boot_splash/minimum_display_time",
+ PROPERTY_HINT_RANGE,
+ "0,100,1,or_greater,suffix:ms")); // No negative numbers.
+
#ifdef TOOLS_ENABLED
if (!doc_tool_path.is_empty()) {
// Needed to instance editor-only classes for their default values
@@ -2704,6 +2725,15 @@ bool Main::start() {
if (movie_writer) {
movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, write_movie_path);
}
+
+ if (minimum_time_msec) {
+ uint64_t minimum_time = 1000 * minimum_time_msec;
+ uint64_t elapsed_time = OS::get_singleton()->get_ticks_usec();
+ if (elapsed_time < minimum_time) {
+ OS::get_singleton()->delay_usec(minimum_time - elapsed_time);
+ }
+ }
+
return true;
}
diff --git a/misc/scripts/install_vulkan_sdk_macos.sh b/misc/scripts/install_vulkan_sdk_macos.sh
new file mode 100755
index 0000000000..e03a907749
--- /dev/null
+++ b/misc/scripts/install_vulkan_sdk_macos.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+IFS=$'\n\t'
+
+# Download and install the Vulkan SDK.
+curl -LO "https://sdk.lunarg.com/sdk/download/latest/mac/vulkan-sdk.dmg"
+hdiutil attach vulkan-sdk.dmg -mountpoint /Volumes/vulkan-sdk
+/Volumes/vulkan-sdk/InstallVulkan.app/Contents/MacOS/InstallVulkan \
+ --accept-licenses --default-answer --confirm-command install
+hdiutil detach /Volumes/vulkan-sdk
+
+echo 'Vulkan SDK installed successfully! You can now build Godot by running "scons".'
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 2c0e604e66..eb5614338b 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -409,9 +409,7 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig
}
Ref<Image> img = memnew(Image(width, height, mipmaps - 1, info.format, src_data));
-
- Ref<ImageTexture> texture = memnew(ImageTexture);
- texture->create_from_image(img);
+ Ref<ImageTexture> texture = ImageTexture::create_from_image(img);
if (r_error) {
*r_error = OK;
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 70151c4d21..049be47ca8 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -257,4 +257,165 @@
[b]Note:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead.
</constant>
</constants>
+ <annotations>
+ <annotation name="@export">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_category">
+ <return type="void" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_color_no_alpha">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_dir">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_enum" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="names" type="String" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_exp_easing">
+ <return type="void" />
+ <argument index="0" name="hint1" type="String" default="null" />
+ <argument index="1" name="hint2" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_file" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="filter" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="names" type="String" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_2d_navigation">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_2d_physics">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_2d_render">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_3d_navigation">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_3d_physics">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_flags_3d_render">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_global_dir">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_global_file" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="filter" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_group">
+ <return type="void" />
+ <argument index="0" name="name" type="String" />
+ <argument index="1" name="prefix" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_multiline">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_node_path" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="type" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_placeholder">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_range">
+ <return type="void" />
+ <argument index="0" name="min" type="float" />
+ <argument index="1" name="max" type="float" />
+ <argument index="2" name="step" type="float" default="null" />
+ <argument index="3" name="slider1" type="String" default="null" />
+ <argument index="4" name="slider2" type="String" default="null" />
+ <argument index="5" name="slider3" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@export_subgroup">
+ <return type="void" />
+ <argument index="0" name="name" type="String" />
+ <argument index="1" name="prefix" type="String" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@icon">
+ <return type="void" />
+ <argument index="0" name="icon_path" type="String" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@onready">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@rpc" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="mode" type="String" default="null" />
+ <argument index="1" name="sync" type="String" default="null" />
+ <argument index="2" name="transfer_mode" type="String" default="null" />
+ <argument index="3" name="transfer_channel" type="int" default="null" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@tool">
+ <return type="void" />
+ <description>
+ </description>
+ </annotation>
+ <annotation name="@warning_ignore" qualifiers="vararg">
+ <return type="void" />
+ <argument index="0" name="warning" type="String" />
+ <description>
+ </description>
+ </annotation>
+ </annotations>
</class>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index e6aeef2fd1..bf83353ead 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1050,7 +1050,7 @@ Error GDScript::load_source_code(const String &p_path) {
w[len] = 0;
String s;
- if (s.parse_utf8((const char *)w)) {
+ if (s.parse_utf8((const char *)w) != OK) {
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
}
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index feb0a237df..e9a206f48b 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -489,6 +489,7 @@ public:
virtual void get_public_functions(List<MethodInfo> *p_functions) const override;
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override;
+ virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override;
virtual void profiling_start() override;
virtual void profiling_stop() override;
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index ea994654bf..8b4c245bf6 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -655,43 +655,43 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
} else {
ERR_PRINT("Parser bug (please report): tried to assign unset node without an identifier.");
}
- } else {
- if (member.variable->datatype_specifier != nullptr) {
- datatype = specified_type;
+ }
- if (member.variable->initializer != nullptr) {
- if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) {
- // Try reverse test since it can be a masked subtype.
- if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) {
- push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer);
- } else {
- // TODO: Add warning.
- mark_node_unsafe(member.variable->initializer);
- member.variable->use_conversion_assign = true;
- }
- } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
-#ifdef DEBUG_ENABLED
- parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION);
-#endif
- }
- if (member.variable->initializer->get_datatype().is_variant()) {
- // TODO: Warn unsafe assign.
+ if (member.variable->datatype_specifier != nullptr) {
+ datatype = specified_type;
+
+ if (member.variable->initializer != nullptr) {
+ if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) {
+ // Try reverse test since it can be a masked subtype.
+ if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) {
+ push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer);
+ } else {
+ // TODO: Add warning.
mark_node_unsafe(member.variable->initializer);
member.variable->use_conversion_assign = true;
}
+ } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) {
+#ifdef DEBUG_ENABLED
+ parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION);
+#endif
}
- } else if (member.variable->infer_datatype) {
- if (member.variable->initializer == nullptr) {
- push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier);
- } else if (!datatype.is_set() || datatype.has_no_type()) {
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer);
- } else if (datatype.is_variant()) {
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer);
- } else if (datatype.builtin_type == Variant::NIL) {
- push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer);
+ if (member.variable->initializer->get_datatype().is_variant()) {
+ // TODO: Warn unsafe assign.
+ mark_node_unsafe(member.variable->initializer);
+ member.variable->use_conversion_assign = true;
}
- datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
}
+ } else if (member.variable->infer_datatype) {
+ if (member.variable->initializer == nullptr) {
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier);
+ } else if (!datatype.is_set() || datatype.has_no_type()) {
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer);
+ } else if (datatype.is_variant()) {
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer);
+ } else if (datatype.builtin_type == Variant::NIL) {
+ push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer);
+ }
+ datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
}
datatype.is_constant = false;
@@ -860,6 +860,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
case GDScriptParser::ClassNode::Member::CLASS:
check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
break;
+ case GDScriptParser::ClassNode::Member::GROUP:
+ // No-op, but needed to silence warnings.
+ break;
case GDScriptParser::ClassNode::Member::UNDEFINED:
ERR_PRINT("Trying to resolve undefined member.");
break;
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 4c15fca91e..48d5fbc569 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -157,7 +157,7 @@ String GDScriptCache::get_source_code(const String &p_path) {
source_file.write[len] = 0;
String source;
- if (source.parse_utf8((const char *)source_file.ptr())) {
+ if (source.parse_utf8((const char *)source_file.ptr()) != OK) {
ERR_FAIL_V_MSG("", "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
}
return source;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 6055d3df33..af8e4b3746 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -2452,6 +2452,25 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
}
#endif
} break;
+
+ case GDScriptParser::ClassNode::Member::GROUP: {
+ const GDScriptParser::AnnotationNode *annotation = member.annotation;
+ StringName name = annotation->export_info.name;
+
+ // This is not a normal member, but we need this to keep indices in order.
+ GDScript::MemberInfo minfo;
+ minfo.index = p_script->member_indices.size();
+
+ PropertyInfo prop_info;
+ prop_info.name = name;
+ prop_info.usage = annotation->export_info.usage;
+ prop_info.hint_string = annotation->export_info.hint_string;
+
+ p_script->member_info[name] = prop_info;
+ p_script->member_indices[name] = minfo;
+ p_script->members.insert(name);
+ } break;
+
default:
break; // Nothing to do here.
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 474c8094f2..0a1e1a22fb 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -445,6 +445,16 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_const
p_constants->push_back(nan);
}
+void GDScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const {
+ GDScriptParser parser;
+ List<MethodInfo> annotations;
+ parser.get_annotation_list(&annotations);
+
+ for (const MethodInfo &E : annotations) {
+ p_annotations->push_back(E);
+ }
+}
+
String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const {
#ifdef TOOLS_ENABLED
bool th = EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints");
@@ -569,7 +579,7 @@ static int _get_enum_constant_location(StringName p_class, StringName p_enum_con
// END LOCATION METHODS
static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) {
- if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
String enum_name = p_info.class_name;
if (!enum_name.contains(".")) {
return enum_name;
@@ -950,6 +960,8 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
}
option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
break;
+ case GDScriptParser::ClassNode::Member::GROUP:
+ break; // No-op, but silences warnings.
case GDScriptParser::ClassNode::Member::UNDEFINED:
break;
}
@@ -1292,7 +1304,7 @@ static GDScriptCompletionIdentifier _type_from_property(const PropertyInfo &p_pr
return ci;
}
- if (p_property.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (p_property.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
ci.enumeration = p_property.class_name;
}
@@ -1843,7 +1855,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
while (suite) {
for (int i = 0; i < suite->statements.size(); i++) {
- if (suite->statements[i]->start_line > p_context.current_line) {
+ if (suite->statements[i]->end_line >= p_context.current_line) {
break;
}
@@ -1891,7 +1903,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
suite = suite->parent_block;
}
- if (last_assigned_expression && last_assign_line != p_context.current_line) {
+ if (last_assigned_expression && last_assign_line < p_context.current_line) {
GDScriptParser::CompletionContext c = p_context;
c.current_line = last_assign_line;
r_type.assigned_expression = last_assigned_expression;
@@ -2028,7 +2040,10 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
return true;
case GDScriptParser::ClassNode::Member::VARIABLE:
if (!is_static) {
- if (member.variable->initializer) {
+ if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
+ r_type.type = member.variable->get_datatype();
+ return true;
+ } else if (member.variable->initializer) {
const GDScriptParser::ExpressionNode *init = member.variable->initializer;
if (init->is_constant) {
r_type.value = init->reduced_value;
@@ -2050,9 +2065,6 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
r_type.type = init->get_datatype();
return true;
}
- } else if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
- r_type.type = member.variable->get_datatype();
- return true;
}
}
// TODO: Check assignments in constructor.
@@ -2082,6 +2094,8 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
r_type.type.kind = GDScriptParser::DataType::CLASS;
r_type.type.class_type = member.m_class;
return true;
+ case GDScriptParser::ClassNode::Member::GROUP:
+ return false; // No-op, but silences warnings.
case GDScriptParser::ClassNode::Member::UNDEFINED:
return false; // Unreachable.
}
@@ -2407,7 +2421,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (p_argidx < method_args) {
PropertyInfo arg_info = info.arguments[p_argidx];
- if (arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
_find_enumeration_candidates(p_context, arg_info.class_name, r_result);
}
}
@@ -3376,6 +3390,15 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
return OK;
}
} break;
+ case GDScriptParser::COMPLETION_ANNOTATION: {
+ const String annotation_symbol = "@" + p_symbol;
+ if (parser.annotation_exists(annotation_symbol)) {
+ r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_ANNOTATION;
+ r_result.class_name = "@GDScript";
+ r_result.class_member = annotation_symbol;
+ return OK;
+ }
+ } break;
default: {
}
}
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index b8670f00d0..632d5ec3ff 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -105,6 +105,10 @@ void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const
}
}
+bool GDScriptParser::annotation_exists(const String &p_annotation_name) const {
+ return valid_annotations.has(p_annotation_name);
+}
+
GDScriptParser::GDScriptParser() {
// Register valid annotations.
// TODO: Should this be static?
@@ -131,6 +135,11 @@ GDScriptParser::GDScriptParser() {
register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_RENDER, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>);
register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>);
+ // Export grouping annotations.
+ register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>);
+ register_annotation(MethodInfo("@export_group", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_GROUP>, 1);
+ register_annotation(MethodInfo("@export_subgroup", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_SUBGROUP>, 1);
+ // Warning annotations.
register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, 0, true);
// Networking.
register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, 4, true);
@@ -519,9 +528,13 @@ void GDScriptParser::parse_program() {
head = alloc_node<ClassNode>();
current_class = head;
+ // If we happen to parse an annotation before extends or class_name keywords, track it.
+ // @tool is allowed, but others should fail.
+ AnnotationNode *premature_annotation = nullptr;
+
if (match(GDScriptTokenizer::Token::ANNOTATION)) {
- // Check for @tool annotation.
- AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL);
+ // Check for @tool, script-level, or standalone annotation.
+ AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL);
if (annotation != nullptr) {
if (annotation->name == SNAME("@tool")) {
// TODO: don't allow @tool anywhere else. (Should all script annotations be the first thing?).
@@ -531,7 +544,14 @@ void GDScriptParser::parse_program() {
}
// @tool annotation has no specific target.
annotation->apply(this, nullptr);
+ } else if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) {
+ premature_annotation = annotation;
+ if (previous.type != GDScriptTokenizer::Token::NEWLINE) {
+ push_error(R"(Expected newline after a standalone annotation.)");
+ }
+ annotation->apply(this, head);
} else {
+ premature_annotation = annotation;
annotation_stack.push_back(annotation);
}
}
@@ -541,8 +561,8 @@ void GDScriptParser::parse_program() {
// Order here doesn't matter, but there should be only one of each at most.
switch (current.type) {
case GDScriptTokenizer::Token::CLASS_NAME:
- if (!annotation_stack.is_empty()) {
- push_error(R"("class_name" should be used before annotations.)");
+ if (premature_annotation != nullptr) {
+ push_error(R"("class_name" should be used before annotations (except @tool).)");
}
advance();
if (head->identifier != nullptr) {
@@ -552,8 +572,8 @@ void GDScriptParser::parse_program() {
}
break;
case GDScriptTokenizer::Token::EXTENDS:
- if (!annotation_stack.is_empty()) {
- push_error(R"("extends" should be used before annotations.)");
+ if (premature_annotation != nullptr) {
+ push_error(R"("extends" should be used before annotations (except @tool).)");
}
advance();
if (head->extends_used) {
@@ -574,12 +594,12 @@ void GDScriptParser::parse_program() {
}
if (match(GDScriptTokenizer::Token::ANNOTATION)) {
- // Check for @icon annotation.
- AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL);
+ // Check for a script-level, or standalone annotation.
+ AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL);
if (annotation != nullptr) {
- if (annotation->name == SNAME("@icon")) {
+ if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) {
if (previous.type != GDScriptTokenizer::Token::NEWLINE) {
- push_error(R"(Expected newline after "@icon" annotation.)");
+ push_error(R"(Expected newline after a standalone annotation.)");
}
annotation->apply(this, head);
} else {
@@ -807,9 +827,18 @@ void GDScriptParser::parse_class_body(bool p_is_multiline) {
break;
case GDScriptTokenizer::Token::ANNOTATION: {
advance();
- AnnotationNode *annotation = parse_annotation(AnnotationInfo::CLASS_LEVEL);
+
+ // Check for class-level annotations.
+ AnnotationNode *annotation = parse_annotation(AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL);
if (annotation != nullptr) {
- annotation_stack.push_back(annotation);
+ if (annotation->applies_to(AnnotationInfo::STANDALONE)) {
+ if (previous.type != GDScriptTokenizer::Token::NEWLINE) {
+ push_error(R"(Expected newline after a standalone annotation.)");
+ }
+ annotation->apply(this, head);
+ } else {
+ annotation_stack.push_back(annotation);
+ }
}
break;
}
@@ -1748,6 +1777,10 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
SuiteNode *suite = alloc_node<SuiteNode>();
if (n_for->variable) {
+ const SuiteNode::Local &local = current_suite->get_local(n_for->variable->name);
+ if (local.type != SuiteNode::Local::UNDEFINED) {
+ push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), n_for->variable->name), n_for->variable);
+ }
suite->add_local(SuiteNode::Local(n_for->variable, current_function));
}
suite->parent_for = n_for;
@@ -3662,6 +3695,36 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
return true;
}
+template <PropertyUsageFlags t_usage>
+bool GDScriptParser::export_group_annotations(const AnnotationNode *p_annotation, Node *p_node) {
+ AnnotationNode *annotation = const_cast<AnnotationNode *>(p_annotation);
+
+ annotation->export_info.name = annotation->resolved_arguments[0];
+
+ switch (t_usage) {
+ case PROPERTY_USAGE_CATEGORY: {
+ annotation->export_info.usage = t_usage;
+ } break;
+
+ case PROPERTY_USAGE_GROUP: {
+ annotation->export_info.usage = t_usage;
+ if (annotation->resolved_arguments.size() == 2) {
+ annotation->export_info.hint_string = annotation->resolved_arguments[1];
+ }
+ } break;
+
+ case PROPERTY_USAGE_SUBGROUP: {
+ annotation->export_info.usage = t_usage;
+ if (annotation->resolved_arguments.size() == 2) {
+ annotation->export_info.hint_string = annotation->resolved_arguments[1];
+ }
+ } break;
+ }
+
+ current_class->add_member_group(annotation);
+ return true;
+}
+
bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Node *p_node) {
#ifdef DEBUG_ENABLED
bool has_error = false;
@@ -4145,6 +4208,8 @@ void GDScriptParser::TreePrinter::print_class(ClassNode *p_class) {
break;
case ClassNode::Member::ENUM_VALUE:
break; // Nothing. Will be printed by enum.
+ case ClassNode::Member::GROUP:
+ break; // Nothing. Groups are only used by inspector.
case ClassNode::Member::UNDEFINED:
push_line("<unknown member>");
break;
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index e3f8d4b8ba..8d3295f25b 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -325,6 +325,7 @@ public:
Vector<Variant> resolved_arguments;
AnnotationInfo *info = nullptr;
+ PropertyInfo export_info;
bool apply(GDScriptParser *p_this, Node *p_target) const;
bool applies_to(uint32_t p_target_kinds) const;
@@ -500,6 +501,7 @@ public:
VARIABLE,
ENUM,
ENUM_VALUE, // For unnamed enums.
+ GROUP, // For member grouping.
};
Type type = UNDEFINED;
@@ -511,6 +513,7 @@ public:
SignalNode *signal;
VariableNode *variable;
EnumNode *m_enum;
+ AnnotationNode *annotation;
};
EnumNode::Value enum_value;
@@ -532,6 +535,8 @@ public:
return "enum";
case ENUM_VALUE:
return "enum value";
+ case GROUP:
+ return "group";
}
return "";
}
@@ -552,6 +557,8 @@ public:
return m_enum->start_line;
case SIGNAL:
return signal->start_line;
+ case GROUP:
+ return annotation->start_line;
case UNDEFINED:
ERR_FAIL_V_MSG(-1, "Reaching undefined member type.");
}
@@ -586,6 +593,9 @@ public:
// TODO: Add parameter info.
return type;
}
+ case GROUP: {
+ return DataType();
+ }
case UNDEFINED:
return DataType();
}
@@ -622,6 +632,10 @@ public:
type = ENUM_VALUE;
enum_value = p_enum_value;
}
+ Member(AnnotationNode *p_annotation) {
+ type = GROUP;
+ annotation = p_annotation;
+ }
};
IdentifierNode *identifier = nullptr;
@@ -668,6 +682,10 @@ public:
members_indices[p_enum_value.identifier->name] = members.size();
members.push_back(Member(p_enum_value));
}
+ void add_member_group(AnnotationNode *p_annotation_node) {
+ members_indices[p_annotation_node->export_info.name] = members.size();
+ members.push_back(Member(p_annotation_node));
+ }
ClassNode() {
type = CLASS;
@@ -1238,6 +1256,7 @@ private:
SIGNAL = 1 << 4,
FUNCTION = 1 << 5,
STATEMENT = 1 << 6,
+ STANDALONE = 1 << 7,
CLASS_LEVEL = CLASS | VARIABLE | FUNCTION,
};
uint32_t target_kind = 0; // Flags.
@@ -1348,6 +1367,8 @@ private:
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target);
template <PropertyHint t_hint, Variant::Type t_type>
bool export_annotations(const AnnotationNode *p_annotation, Node *p_target);
+ template <PropertyUsageFlags t_usage>
+ bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target);
bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target);
template <Multiplayer::RPCMode t_mode>
bool network_annotations(const AnnotationNode *p_annotation, Node *p_target);
@@ -1413,6 +1434,7 @@ public:
CompletionContext get_completion_context() const { return completion_context; }
CompletionCall get_completion_call() const { return completion_call; }
void get_annotation_list(List<MethodInfo> *r_annotations) const;
+ bool annotation_exists(const String &p_annotation_name) const;
const List<ParserError> &get_errors() const { return errors; }
const List<String> get_dependencies() const {
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index d3c5fed95a..03e93821c7 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -307,6 +307,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
parse_class_symbol(m.m_class, symbol);
r_symbol.children.push_back(symbol);
} break;
+ case ClassNode::Member::GROUP:
+ break; // No-op, but silences warnings.
case ClassNode::Member::UNDEFINED:
break; // Unreachable.
}
@@ -815,6 +817,8 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
methods.append(dump_function_api(m.function));
}
} break;
+ case ClassNode::Member::GROUP:
+ break; // No-op, but silences warnings.
case ClassNode::Member::UNDEFINED:
break; // Unreachable.
}
diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
index d13d713454..ada6030132 100644
--- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
@@ -1,6 +1,6 @@
-# Error here. `class_name` should be used *before* annotations, not after.
+# Error here. `class_name` should be used *before* annotations, not after (except @tool).
@icon("res://path/to/optional/icon.svg")
class_name HelloWorld
func test():
- pass
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
index 0bcc8acc55..02b33c8692 100644
--- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
+++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-"class_name" should be used before annotations.
+"class_name" should be used before annotations (except @tool).
diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd
new file mode 100644
index 0000000000..409da11051
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd
@@ -0,0 +1,4 @@
+func test():
+ var TEST = 1
+ for TEST in 2:
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out
new file mode 100644
index 0000000000..407f094ca0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+There is already a variable named "TEST" declared in this scope.
diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd
new file mode 100644
index 0000000000..b353fd1288
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd
@@ -0,0 +1,3 @@
+func test():
+ var TEST = 1
+ var TEST = 2
diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out
new file mode 100644
index 0000000000..407f094ca0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+There is already a variable named "TEST" declared in this scope.
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 2017355717..babdc9f33b 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -3080,9 +3080,9 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
// We'll assume that we use either URI or bufferView, so let's warn the user
// if their image somehow uses both. And fail if it has neither.
- ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specific an 'uri' or 'bufferView'.");
+ ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specify an 'uri' or 'bufferView'.");
if (d.has("uri") && d.has("bufferView")) {
- WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'bufferView' will take precedence.");
+ WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'uri' will take precedence.");
}
String mimetype;
@@ -3202,12 +3202,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
state->images.push_back(Ref<Texture2D>());
continue;
}
-
- Ref<ImageTexture> t;
- t.instantiate();
- t->create_from_image(img);
-
- state->images.push_back(t);
+ state->images.push_back(ImageTexture::create_from_image(img));
}
print_verbose("glTF: Total images: " + itos(state->images.size()));
@@ -3428,7 +3423,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
}
}
orm_image->generate_mipmaps();
- orm_texture->create_from_image(orm_image);
+ orm_texture->set_image(orm_image);
GLTFTextureIndex orm_texture_index = -1;
if (has_ao || has_roughness || has_metalness) {
orm_texture->set_name(material->get_name() + "_orm");
@@ -3476,7 +3471,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
img->set_pixel(x, y, c);
}
}
- tex->create_from_image(img);
+ tex->set_image(img);
}
}
}
@@ -3784,13 +3779,8 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re
}
rm_img->generate_mipmaps();
r_spec_gloss->diffuse_img->generate_mipmaps();
- Ref<ImageTexture> diffuse_image_texture;
- diffuse_image_texture.instantiate();
- diffuse_image_texture->create_from_image(r_spec_gloss->diffuse_img);
- p_material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_image_texture);
- Ref<ImageTexture> rm_image_texture;
- rm_image_texture.instantiate();
- rm_image_texture->create_from_image(rm_img);
+ p_material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, ImageTexture::create_from_image(r_spec_gloss->diffuse_img));
+ Ref<ImageTexture> rm_image_texture = ImageTexture::create_from_image(rm_img);
if (has_roughness) {
p_material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, rm_image_texture);
p_material->set_roughness_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_GREEN);
@@ -5176,19 +5166,16 @@ Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex
}
const float range = CLAMP(l->range, 0, 4096);
- // Doubling the range will double the effective brightness, so we need double attenuation (half brightness).
- // We want to have double intensity give double brightness, so we need half the attenuation.
- const float attenuation = range / (intensity * 2048);
if (l->light_type == "point") {
OmniLight3D *light = memnew(OmniLight3D);
- light->set_param(OmniLight3D::PARAM_ATTENUATION, attenuation);
+ light->set_param(OmniLight3D::PARAM_ENERGY, intensity);
light->set_param(OmniLight3D::PARAM_RANGE, range);
light->set_color(l->color);
return light;
}
if (l->light_type == "spot") {
SpotLight3D *light = memnew(SpotLight3D);
- light->set_param(SpotLight3D::PARAM_ATTENUATION, attenuation);
+ light->set_param(SpotLight3D::PARAM_ENERGY, intensity);
light->set_param(SpotLight3D::PARAM_RANGE, range);
light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle));
light->set_color(l->color);
@@ -5253,14 +5240,12 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_lig
l->light_type = "point";
OmniLight3D *light = cast_to<OmniLight3D>(p_light);
l->range = light->get_param(OmniLight3D::PARAM_RANGE);
- float attenuation = p_light->get_param(OmniLight3D::PARAM_ATTENUATION);
- l->intensity = l->range / (attenuation * 2048);
+ l->intensity = light->get_param(OmniLight3D::PARAM_ENERGY);
} else if (cast_to<SpotLight3D>(p_light)) {
l->light_type = "spot";
SpotLight3D *light = cast_to<SpotLight3D>(p_light);
l->range = light->get_param(SpotLight3D::PARAM_RANGE);
- float attenuation = light->get_param(SpotLight3D::PARAM_ATTENUATION);
- l->intensity = l->range / (attenuation * 2048);
+ l->intensity = light->get_param(SpotLight3D::PARAM_ENERGY);
l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE));
// This equation is the inverse of the import equation (which has a desmos link).
diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub
index 5cc9d8ee8b..fe9737b36f 100644
--- a/modules/lightmapper_rd/SCsub
+++ b/modules/lightmapper_rd/SCsub
@@ -7,9 +7,7 @@ env_lightmapper_rd = env_modules.Clone()
env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl")
env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl")
env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl")
-env_lightmapper_rd.Depends("lm_raster.glsl.gen.h", "lm_common_inc.glsl")
-env_lightmapper_rd.Depends("lm_compute.glsl.gen.h", "lm_common_inc.glsl")
-env_lightmapper_rd.Depends("lm_blendseams.glsl.gen.h", "lm_common_inc.glsl")
+env_lightmapper_rd.Depends(Glob("*.glsl.gen.h"), ["lm_common_inc.glsl", "#glsl_builders.py"])
# Godot source files
env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py
index 1920ef1c1a..3459244bc2 100644
--- a/modules/mono/build_scripts/make_android_mono_config.py
+++ b/modules/mono/build_scripts/make_android_mono_config.py
@@ -43,7 +43,7 @@ String get_godot_android_mono_config() {
Compression::decompress(w, config_uncompressed_size, config_compressed_data,
config_compressed_size, Compression::MODE_DEFLATE);
String s;
- if (s.parse_utf8((const char *)w, data.size())) {
+ if (s.parse_utf8((const char *)w, data.size()) != OK) {
ERR_FAIL_V(String());
}
return s;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 622838b308..3dc26cfbe4 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2866,6 +2866,12 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
r_hint = PROPERTY_HINT_RESOURCE_TYPE;
r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class));
+ } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(Node)->is_assignable_from(p_type.type_class)) {
+ GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class);
+ CRASH_COND(field_native_class == nullptr);
+
+ r_hint = PROPERTY_HINT_NODE_TYPE;
+ r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class));
} else if (p_allow_generics && p_variant_type == Variant::ARRAY) {
// Nested arrays are not supported in the inspector
@@ -3063,16 +3069,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
Vector<GDMonoMethod *> methods = top->get_all_methods();
for (int i = 0; i < methods.size(); i++) {
if (!methods[i]->is_static()) {
- Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]);
- if (Multiplayer::RPC_MODE_DISABLED != mode) {
- Multiplayer::RPCConfig nd;
- nd.name = methods[i]->get_name();
- nd.rpc_mode = mode;
- // TODO Transfer mode, channel
- nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE;
- nd.channel = 0;
- if (-1 == p_script->rpc_functions.find(nd)) {
- p_script->rpc_functions.push_back(nd);
+ Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]);
+ if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) {
+ // RPC annotations can only be used once per method
+ if (p_script->rpc_functions.find(rpc_config) == -1) {
+ p_script->rpc_functions.push_back(rpc_config);
}
}
}
@@ -3507,15 +3508,19 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
return -1;
}
-Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const {
- if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) {
- return Multiplayer::RPC_MODE_ANY_PEER;
- }
- if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) {
- return Multiplayer::RPC_MODE_AUTHORITY;
+Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const {
+ Multiplayer::RPCConfig rpc_config;
+
+ MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute));
+ if (rpc_attribute != nullptr) {
+ rpc_config.name = p_member->get_name();
+ rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute);
+ rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute);
+ rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute);
+ rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute);
}
- return Multiplayer::RPC_MODE_DISABLED;
+ return rpc_config;
}
const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 69bd8703aa..b17473470f 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -179,7 +179,7 @@ private:
static void update_script_class_info(Ref<CSharpScript> p_script);
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
- Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
+ Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const;
protected:
static void _bind_methods();
@@ -502,6 +502,7 @@ public:
/* TODO? */ void get_public_functions(List<MethodInfo> *p_functions) const override {}
/* TODO? */ void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {}
+ /* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {}
void reload_all_scripts() override;
void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override;
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
index 16dd1c8c6b..63b97e981e 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs
@@ -99,7 +99,7 @@ namespace GodotTools.Build
if (Utils.OS.IsWindows)
{
// %APPDATA% for both
- return new[] {Path.Combine(applicationData, "NuGet", "NuGet.Config")};
+ return new[] { Path.Combine(applicationData, "NuGet", "NuGet.Config") };
}
var paths = new string[2];
@@ -156,6 +156,7 @@ namespace GodotTools.Build
</packageSources>
</configuration>
";
+ System.IO.Directory.CreateDirectory(Path.GetDirectoryName(nuGetConfigPath));
System.IO.File.WriteAllText(nuGetConfigPath, defaultConfig, Encoding.UTF8); // UTF-8 with BOM
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 9d3d481068..7cc195201b 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -990,6 +990,10 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append("\n" INDENT1 OPEN_BLOCK);
}
+ if (ienum.is_flags) {
+ p_output.append("\n" INDENT1 "[System.Flags]");
+ }
+
p_output.append("\n" INDENT1 "public enum ");
p_output.append(enum_proxy_name);
p_output.append(" : long");
@@ -1434,6 +1438,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
for (const EnumInterface &ienum : itype.enums) {
ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG);
+ if (ienum.is_flags) {
+ output.append(MEMBER_BEGIN "[System.Flags]");
+ }
+
output.append(MEMBER_BEGIN "public enum ");
output.append(ienum.cname.operator String());
output.append(" : long");
@@ -2865,7 +2873,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
" We only expected Object.free, but found '" +
itype.name + "." + imethod.name + "'.");
}
- } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ } else if (return_info.type == Variant::INT && return_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
imethod.return_type.cname = return_info.class_name;
imethod.return_type.is_enum = true;
} else if (return_info.class_name != StringName()) {
@@ -2903,7 +2911,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ArgumentInterface iarg;
iarg.name = orig_arg_name;
- if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
iarg.type.cname = arginfo.class_name;
iarg.type.is_enum = true;
} else if (arginfo.class_name != StringName()) {
@@ -3011,7 +3019,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ArgumentInterface iarg;
iarg.name = orig_arg_name;
- if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
iarg.type.cname = arginfo.class_name;
iarg.type.is_enum = true;
} else if (arginfo.class_name != StringName()) {
@@ -3075,9 +3083,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
List<String> constants;
ClassDB::get_integer_constant_list(type_cname, &constants, true);
- const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
+ const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map;
- for (const KeyValue<StringName, List<StringName>> &E : enum_map) {
+ for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) {
StringName enum_proxy_cname = E.key;
String enum_proxy_name = enum_proxy_cname.operator String();
if (itype.find_property_by_proxy_name(enum_proxy_cname)) {
@@ -3087,7 +3095,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_proxy_cname = StringName(enum_proxy_name);
}
EnumInterface ienum(enum_proxy_cname);
- const List<StringName> &enum_constants = E.value;
+ ienum.is_flags = E.value.is_bitfield;
+ const List<StringName> &enum_constants = E.value.constants;
for (const StringName &constant_cname : enum_constants) {
String constant_name = constant_cname.operator String();
int64_t *value = class_info->constant_map.getptr(constant_cname);
@@ -3676,6 +3685,7 @@ void BindingsGenerator::_populate_global_constants() {
if (enum_name != StringName()) {
EnumInterface ienum(enum_name);
+ // TODO: ienum.is_flags is always false for core constants since they don't seem to support bitfield enums
List<EnumInterface>::Element *enum_match = global_enums.find(ienum);
if (enum_match) {
enum_match->get().constants.push_back(iconstant);
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 70c4f12146..1547d0ed2f 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -60,6 +60,7 @@ class BindingsGenerator {
struct EnumInterface {
StringName cname;
List<ConstantInterface> constants;
+ bool is_flags = false;
_FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
return p_ienum.cname == cname;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
new file mode 100644
index 0000000000..0a1c8322d7
--- /dev/null
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Godot
+{
+ /// <summary>
+ /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>,
+ /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers).
+ /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking
+ /// (and RPCs).
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+ public class RPCAttribute : Attribute
+ {
+ /// <summary>
+ /// RPC mode for the annotated method.
+ /// </summary>
+ public RPCMode Mode { get; } = RPCMode.Disabled;
+
+ /// <summary>
+ /// If the method will also be called locally; otherwise, it is only called remotely.
+ /// </summary>
+ public bool CallLocal { get; set; } = false;
+
+ /// <summary>
+ /// Transfer mode for the annotated method.
+ /// </summary>
+ public TransferMode TransferMode { get; set; } = TransferMode.Reliable;
+
+ /// <summary>
+ /// Transfer channel for the annotated mode.
+ /// </summary>
+ public int TransferChannel { get; set; } = 0;
+
+ /// <summary>
+ /// Constructs a <see cref="RPCAttribute"/> instance.
+ /// </summary>
+ /// <param name="mode">The RPC mode to use.</param>
+ public RPCAttribute(RPCMode mode = RPCMode.Authority)
+ {
+ Mode = mode;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
deleted file mode 100644
index f0d37c344d..0000000000
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace Godot
-{
- /// <summary>
- /// Constructs a new AnyPeerAttribute instance. Members with the AnyPeerAttribute are given authority over their own player.
- /// </summary>
- [AttributeUsage(AttributeTargets.Method)]
- public class AnyPeerAttribute : Attribute { }
-
- /// <summary>
- /// Constructs a new AuthorityAttribute instance. Members with the AuthorityAttribute are given authority over the game.
- /// </summary>
- [AttributeUsage(AttributeTargets.Method)]
- public class AuthorityAttribute : Attribute { }
-}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index 2b820070d6..36b7d0f80f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -198,6 +198,28 @@ namespace Godot
}
/// <summary>
+ /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by
+ /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="start">The start value for the interpolation.</param>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination value for the interpolation.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The resulting value of the interpolation.</returns>
+ public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ real_t omt = 1 - t;
+ real_t omt2 = omt * omt;
+ real_t omt3 = omt2 * omt;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ }
+
+ /// <summary>
/// Converts an angle expressed in degrees to radians.
/// </summary>
/// <param name="deg">An angle expressed in degrees.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
index 40fb5f8788..9ae01016cb 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs
@@ -170,6 +170,21 @@ namespace Godot
}
/// <summary>
+ /// Returns all names concatenated with a slash character (<c>/</c>).
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// var nodepath = new NodePath("Path2D/PathFollow2D/Sprite2D:texture:load_path");
+ /// GD.Print(nodepath.GetConcatenatedNames()); // Path2D/PathFollow2D/Sprite2D
+ /// </code>
+ /// </example>
+ /// <returns>The names concatenated with <c>/</c>.</returns>
+ public string GetConcatenatedNames()
+ {
+ return godot_icall_NodePath_get_concatenated_names(GetPtr(this));
+ }
+
+ /// <summary>
/// Returns all subnames concatenated with a colon character (<c>:</c>)
/// as separator, i.e. the right side of the first colon in a node path.
/// </summary>
@@ -269,6 +284,9 @@ namespace Godot
private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern string godot_icall_NodePath_get_concatenated_names(IntPtr ptr);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 9e990ce83e..7bdbe1c28b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -221,6 +221,27 @@ namespace Godot
}
/// <summary>
+ /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination vector.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The interpolated vector.</returns>
+ public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ real_t omt = 1 - t;
+ real_t omt2 = omt * omt;
+ real_t omt3 = omt2 * omt;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ }
+
+ /// <summary>
/// Returns the normalized vector pointing from this vector to <paramref name="to"/>.
/// </summary>
/// <param name="to">The other vector to point towards.</param>
@@ -522,9 +543,10 @@ namespace Godot
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
- if (startLengthSquared == 0.0 || endLengthSquared == 0.0) {
- // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
- return Lerp(to, weight);
+ if (startLengthSquared == 0.0 || endLengthSquared == 0.0)
+ {
+ // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
+ return Lerp(to, weight);
}
real_t startLength = Mathf.Sqrt(startLengthSquared);
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 56859da7f2..480165d44a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -214,6 +214,27 @@ namespace Godot
}
/// <summary>
+ /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector
+ /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points.
+ /// </summary>
+ /// <param name="control1">Control point that defines the bezier curve.</param>
+ /// <param name="control2">Control point that defines the bezier curve.</param>
+ /// <param name="end">The destination vector.</param>
+ /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
+ /// <returns>The interpolated vector.</returns>
+ public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t)
+ {
+ // Formula from Wikipedia article on Bezier curves
+ real_t omt = 1 - t;
+ real_t omt2 = omt * omt;
+ real_t omt3 = omt2 * omt;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3;
+ }
+
+ /// <summary>
/// Returns the normalized vector pointing from this vector to <paramref name="to"/>.
/// </summary>
/// <param name="to">The other vector to point towards.</param>
@@ -562,9 +583,10 @@ namespace Godot
{
real_t startLengthSquared = LengthSquared();
real_t endLengthSquared = to.LengthSquared();
- if (startLengthSquared == 0.0 || endLengthSquared == 0.0) {
- // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
- return Lerp(to, weight);
+ if (startLengthSquared == 0.0 || endLengthSquared == 0.0)
+ {
+ // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
+ return Lerp(to, weight);
}
real_t startLength = Mathf.Sqrt(startLengthSquared);
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 1fcfe74c86..e59f45bbf6 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -18,7 +18,7 @@
<Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" />
<Compile Include="Core\Attributes\ExportAttribute.cs" />
<Compile Include="Core\Attributes\GodotMethodAttribute.cs" />
- <Compile Include="Core\Attributes\RPCAttributes.cs" />
+ <Compile Include="Core\Attributes\RPCAttribute.cs" />
<Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
<Compile Include="Core\Attributes\SignalAttribute.cs" />
<Compile Include="Core\Attributes\ToolAttribute.cs" />
diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp
index 0ea9814b1a..16e1509eb0 100644
--- a/modules/mono/glue/nodepath_glue.cpp
+++ b/modules/mono/glue/nodepath_glue.cpp
@@ -68,6 +68,10 @@ MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) {
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx));
}
+MonoString *godot_icall_NodePath_get_concatenated_names(NodePath *p_ptr) {
+ return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_names());
+}
+
MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
}
@@ -85,6 +89,7 @@ void godot_register_nodepath_icalls() {
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path);
+ GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name);
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count);
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index 44a8e26b8f..fd78fae4ad 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -140,8 +140,11 @@ void CachedData::clear_godot_api_cache() {
field_ExportAttribute_hintString = nullptr;
class_SignalAttribute = nullptr;
class_ToolAttribute = nullptr;
- class_AnyPeerAttribute = nullptr;
- class_AuthorityAttribute = nullptr;
+ class_RPCAttribute = nullptr;
+ property_RPCAttribute_Mode = nullptr;
+ property_RPCAttribute_CallLocal = nullptr;
+ property_RPCAttribute_TransferMode = nullptr;
+ property_RPCAttribute_TransferChannel = nullptr;
class_GodotMethodAttribute = nullptr;
field_GodotMethodAttribute_methodName = nullptr;
class_ScriptPathAttribute = nullptr;
@@ -268,8 +271,11 @@ void update_godot_api_cache() {
CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString"));
CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute));
CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
- CACHE_CLASS_AND_CHECK(AnyPeerAttribute, GODOT_API_CLASS(AnyPeerAttribute));
- CACHE_CLASS_AND_CHECK(AuthorityAttribute, GODOT_API_CLASS(AuthorityAttribute));
+ CACHE_CLASS_AND_CHECK(RPCAttribute, GODOT_API_CLASS(RPCAttribute));
+ CACHE_PROPERTY_AND_CHECK(RPCAttribute, Mode, CACHED_CLASS(RPCAttribute)->get_property("Mode"));
+ CACHE_PROPERTY_AND_CHECK(RPCAttribute, CallLocal, CACHED_CLASS(RPCAttribute)->get_property("CallLocal"));
+ CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferMode, CACHED_CLASS(RPCAttribute)->get_property("TransferMode"));
+ CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferChannel, CACHED_CLASS(RPCAttribute)->get_property("TransferChannel"));
CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute));
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 92136e1f41..b3b0865608 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -111,8 +111,11 @@ struct CachedData {
GDMonoField *field_ExportAttribute_hintString = nullptr;
GDMonoClass *class_SignalAttribute = nullptr;
GDMonoClass *class_ToolAttribute = nullptr;
- GDMonoClass *class_AnyPeerAttribute = nullptr;
- GDMonoClass *class_AuthorityAttribute = nullptr;
+ GDMonoClass *class_RPCAttribute = nullptr;
+ GDMonoProperty *property_RPCAttribute_Mode = nullptr;
+ GDMonoProperty *property_RPCAttribute_CallLocal = nullptr;
+ GDMonoProperty *property_RPCAttribute_TransferMode = nullptr;
+ GDMonoProperty *property_RPCAttribute_TransferChannel = nullptr;
GDMonoClass *class_GodotMethodAttribute = nullptr;
GDMonoField *field_GodotMethodAttribute_methodName = nullptr;
GDMonoClass *class_ScriptPathAttribute = nullptr;
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 15a0b28181..a1905dfcfe 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -62,7 +62,8 @@ String cwd() {
}
String result;
- if (result.parse_utf16(buffer.ptr())) {
+ result.parse_utf16(buffer.ptr());
+ if (result.is_empty()) {
return ".";
}
return result.simplify_path();
@@ -73,7 +74,7 @@ String cwd() {
}
String result;
- if (result.parse_utf8(buffer)) {
+ if (result.parse_utf8(buffer) != OK) {
return ".";
}
@@ -114,7 +115,8 @@ String realpath(const String &p_path) {
::CloseHandle(hFile);
String result;
- if (result.parse_utf16(buffer.ptr())) {
+ result.parse_utf16(buffer.ptr());
+ if (result.is_empty()) {
return p_path;
}
@@ -127,10 +129,10 @@ String realpath(const String &p_path) {
}
String result;
- bool parse_ok = result.parse_utf8(resolved_path);
+ Error parse_ok = result.parse_utf8(resolved_path);
::free(resolved_path);
- if (parse_ok) {
+ if (parse_ok != OK) {
return p_path;
}
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 64b68b70af..975f2d8332 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -178,7 +178,7 @@ Error read_all_file_utf8(const String &p_path, String &r_content) {
w[len] = 0;
String source;
- if (source.parse_utf8((const char *)w)) {
+ if (source.parse_utf8((const char *)w) != OK) {
ERR_FAIL_V(ERR_INVALID_DATA);
}
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index 2ddf3b8a7d..3d3d4de5b6 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp
@@ -34,7 +34,6 @@
#include "../openxr_api.h"
#include "../openxr_util.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering_server.h"
@@ -439,7 +438,6 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target
SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data;
ERR_FAIL_NULL_V(data, false);
ERR_FAIL_COND_V(p_from_render_target.is_null(), false);
- ERR_FAIL_NULL_V(RendererStorageRD::base_singleton, false);
RID source_image = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(p_from_render_target);
ERR_FAIL_COND_V(source_image.is_null(), false);
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index a46f17311a..2d764a4006 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -75,18 +75,18 @@ if env["builtin_harfbuzz"]:
"src/hb-ot-meta.cc",
"src/hb-ot-metrics.cc",
"src/hb-ot-name.cc",
- "src/hb-ot-shape-complex-arabic.cc",
- "src/hb-ot-shape-complex-default.cc",
- "src/hb-ot-shape-complex-hangul.cc",
- "src/hb-ot-shape-complex-hebrew.cc",
- "src/hb-ot-shape-complex-indic-table.cc",
- "src/hb-ot-shape-complex-indic.cc",
- "src/hb-ot-shape-complex-khmer.cc",
- "src/hb-ot-shape-complex-myanmar.cc",
- "src/hb-ot-shape-complex-syllabic.cc",
- "src/hb-ot-shape-complex-thai.cc",
- "src/hb-ot-shape-complex-use.cc",
- "src/hb-ot-shape-complex-vowel-constraints.cc",
+ "src/hb-ot-shaper-arabic.cc",
+ "src/hb-ot-shaper-default.cc",
+ "src/hb-ot-shaper-hangul.cc",
+ "src/hb-ot-shaper-hebrew.cc",
+ "src/hb-ot-shaper-indic-table.cc",
+ "src/hb-ot-shaper-indic.cc",
+ "src/hb-ot-shaper-khmer.cc",
+ "src/hb-ot-shaper-myanmar.cc",
+ "src/hb-ot-shaper-syllabic.cc",
+ "src/hb-ot-shaper-thai.cc",
+ "src/hb-ot-shaper-use.cc",
+ "src/hb-ot-shaper-vowel-constraints.cc",
"src/hb-ot-shape-fallback.cc",
"src/hb-ot-shape-normalize.cc",
"src/hb-ot-shape.cc",
diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct
index 0e36ef6805..69848a9e52 100644
--- a/modules/text_server_adv/gdextension_build/SConstruct
+++ b/modules/text_server_adv/gdextension_build/SConstruct
@@ -220,18 +220,18 @@ thirdparty_harfbuzz_sources = [
"src/hb-ot-meta.cc",
"src/hb-ot-metrics.cc",
"src/hb-ot-name.cc",
- "src/hb-ot-shape-complex-arabic.cc",
- "src/hb-ot-shape-complex-default.cc",
- "src/hb-ot-shape-complex-hangul.cc",
- "src/hb-ot-shape-complex-hebrew.cc",
- "src/hb-ot-shape-complex-indic-table.cc",
- "src/hb-ot-shape-complex-indic.cc",
- "src/hb-ot-shape-complex-khmer.cc",
- "src/hb-ot-shape-complex-myanmar.cc",
- "src/hb-ot-shape-complex-syllabic.cc",
- "src/hb-ot-shape-complex-thai.cc",
- "src/hb-ot-shape-complex-use.cc",
- "src/hb-ot-shape-complex-vowel-constraints.cc",
+ "src/hb-ot-shaper-arabic.cc",
+ "src/hb-ot-shaper-default.cc",
+ "src/hb-ot-shaper-hangul.cc",
+ "src/hb-ot-shaper-hebrew.cc",
+ "src/hb-ot-shaper-indic-table.cc",
+ "src/hb-ot-shaper-indic.cc",
+ "src/hb-ot-shaper-khmer.cc",
+ "src/hb-ot-shaper-myanmar.cc",
+ "src/hb-ot-shaper-syllabic.cc",
+ "src/hb-ot-shaper-thai.cc",
+ "src/hb-ot-shaper-use.cc",
+ "src/hb-ot-shaper-vowel-constraints.cc",
"src/hb-ot-shape-fallback.cc",
"src/hb-ot-shape-normalize.cc",
"src/hb-ot-shape.cc",
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index c4269a53f4..6076b87203 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -75,7 +75,7 @@ using namespace core_bind;
hb_font_funcs_t *TextServerAdvanced::funcs = nullptr;
-TextServerAdvanced::bmp_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) {
+TextServerAdvanced::bmp_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref) {
bmp_font_t *bm_font = memnew(bmp_font_t);
if (!bm_font) {
@@ -228,11 +228,11 @@ void TextServerAdvanced::_bmp_free_font_funcs() {
}
}
-void TextServerAdvanced::_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) {
+void TextServerAdvanced::_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref) {
hb_font_set_funcs(p_font, funcs, _bmp_font_create(p_face, p_unref), _bmp_font_destroy);
}
-hb_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) {
+hb_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) {
hb_font_t *font;
hb_face_t *face = hb_face_create(nullptr, 0);
@@ -375,7 +375,7 @@ int64_t TextServerAdvanced::get_features() const {
void TextServerAdvanced::free_rid(const RID &p_rid) {
_THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_rid);
font_owner.free(p_rid);
memdelete(fd);
} else if (shaped_owner.owns(p_rid)) {
@@ -476,259 +476,267 @@ bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) const {
}
}
-_FORCE_INLINE_ void TextServerAdvanced::_insert_feature(const StringName &p_name, int32_t p_tag) {
+_FORCE_INLINE_ void TextServerAdvanced::_insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype, bool p_hidden) {
+ FeatureInfo fi;
+ fi.name = p_name;
+ fi.vtype = p_vtype;
+ fi.hidden = p_hidden;
+
feature_sets.insert(p_name, p_tag);
- feature_sets_inv.insert(p_tag, p_name);
+ feature_sets_inv.insert(p_tag, fi);
}
void TextServerAdvanced::_insert_feature_sets() {
// Registered OpenType feature tags.
- _insert_feature("access_all_alternates", HB_TAG('a', 'a', 'l', 't'));
- _insert_feature("above_base_forms", HB_TAG('a', 'b', 'v', 'f'));
- _insert_feature("above_base_mark_positioning", HB_TAG('a', 'b', 'v', 'm'));
- _insert_feature("above_base_substitutions", HB_TAG('a', 'b', 'v', 's'));
- _insert_feature("alternative_fractions", HB_TAG('a', 'f', 'r', 'c'));
- _insert_feature("akhands", HB_TAG('a', 'k', 'h', 'n'));
- _insert_feature("below_base_forms", HB_TAG('b', 'l', 'w', 'f'));
- _insert_feature("below_base_mark_positioning", HB_TAG('b', 'l', 'w', 'm'));
- _insert_feature("below_base_substitutions", HB_TAG('b', 'l', 'w', 's'));
- _insert_feature("contextual_alternates", HB_TAG('c', 'a', 'l', 't'));
- _insert_feature("case_sensitive_forms", HB_TAG('c', 'a', 's', 'e'));
- _insert_feature("glyph_composition", HB_TAG('c', 'c', 'm', 'p'));
- _insert_feature("conjunct_form_after_ro", HB_TAG('c', 'f', 'a', 'r'));
- _insert_feature("conjunct_forms", HB_TAG('c', 'j', 'c', 't'));
- _insert_feature("contextual_ligatures", HB_TAG('c', 'l', 'i', 'g'));
- _insert_feature("centered_cjk_punctuation", HB_TAG('c', 'p', 'c', 't'));
- _insert_feature("capital_spacing", HB_TAG('c', 'p', 's', 'p'));
- _insert_feature("contextual_swash", HB_TAG('c', 's', 'w', 'h'));
- _insert_feature("cursive_positioning", HB_TAG('c', 'u', 'r', 's'));
- _insert_feature("character_variant_01", HB_TAG('c', 'v', '0', '1'));
- _insert_feature("character_variant_02", HB_TAG('c', 'v', '0', '2'));
- _insert_feature("character_variant_03", HB_TAG('c', 'v', '0', '3'));
- _insert_feature("character_variant_04", HB_TAG('c', 'v', '0', '4'));
- _insert_feature("character_variant_05", HB_TAG('c', 'v', '0', '5'));
- _insert_feature("character_variant_06", HB_TAG('c', 'v', '0', '6'));
- _insert_feature("character_variant_07", HB_TAG('c', 'v', '0', '7'));
- _insert_feature("character_variant_08", HB_TAG('c', 'v', '0', '8'));
- _insert_feature("character_variant_09", HB_TAG('c', 'v', '0', '9'));
- _insert_feature("character_variant_10", HB_TAG('c', 'v', '1', '0'));
- _insert_feature("character_variant_11", HB_TAG('c', 'v', '1', '1'));
- _insert_feature("character_variant_12", HB_TAG('c', 'v', '1', '2'));
- _insert_feature("character_variant_13", HB_TAG('c', 'v', '1', '3'));
- _insert_feature("character_variant_14", HB_TAG('c', 'v', '1', '4'));
- _insert_feature("character_variant_15", HB_TAG('c', 'v', '1', '5'));
- _insert_feature("character_variant_16", HB_TAG('c', 'v', '1', '6'));
- _insert_feature("character_variant_17", HB_TAG('c', 'v', '1', '7'));
- _insert_feature("character_variant_18", HB_TAG('c', 'v', '1', '8'));
- _insert_feature("character_variant_19", HB_TAG('c', 'v', '1', '9'));
- _insert_feature("character_variant_20", HB_TAG('c', 'v', '2', '0'));
- _insert_feature("character_variant_21", HB_TAG('c', 'v', '2', '1'));
- _insert_feature("character_variant_22", HB_TAG('c', 'v', '2', '2'));
- _insert_feature("character_variant_23", HB_TAG('c', 'v', '2', '3'));
- _insert_feature("character_variant_24", HB_TAG('c', 'v', '2', '4'));
- _insert_feature("character_variant_25", HB_TAG('c', 'v', '2', '5'));
- _insert_feature("character_variant_26", HB_TAG('c', 'v', '2', '6'));
- _insert_feature("character_variant_27", HB_TAG('c', 'v', '2', '7'));
- _insert_feature("character_variant_28", HB_TAG('c', 'v', '2', '8'));
- _insert_feature("character_variant_29", HB_TAG('c', 'v', '2', '9'));
- _insert_feature("character_variant_30", HB_TAG('c', 'v', '3', '0'));
- _insert_feature("character_variant_31", HB_TAG('c', 'v', '3', '1'));
- _insert_feature("character_variant_32", HB_TAG('c', 'v', '3', '2'));
- _insert_feature("character_variant_33", HB_TAG('c', 'v', '3', '3'));
- _insert_feature("character_variant_34", HB_TAG('c', 'v', '3', '4'));
- _insert_feature("character_variant_35", HB_TAG('c', 'v', '3', '5'));
- _insert_feature("character_variant_36", HB_TAG('c', 'v', '3', '6'));
- _insert_feature("character_variant_37", HB_TAG('c', 'v', '3', '7'));
- _insert_feature("character_variant_38", HB_TAG('c', 'v', '3', '8'));
- _insert_feature("character_variant_39", HB_TAG('c', 'v', '3', '9'));
- _insert_feature("character_variant_40", HB_TAG('c', 'v', '4', '0'));
- _insert_feature("character_variant_41", HB_TAG('c', 'v', '4', '1'));
- _insert_feature("character_variant_42", HB_TAG('c', 'v', '4', '2'));
- _insert_feature("character_variant_43", HB_TAG('c', 'v', '4', '3'));
- _insert_feature("character_variant_44", HB_TAG('c', 'v', '4', '4'));
- _insert_feature("character_variant_45", HB_TAG('c', 'v', '4', '5'));
- _insert_feature("character_variant_46", HB_TAG('c', 'v', '4', '6'));
- _insert_feature("character_variant_47", HB_TAG('c', 'v', '4', '7'));
- _insert_feature("character_variant_48", HB_TAG('c', 'v', '4', '8'));
- _insert_feature("character_variant_49", HB_TAG('c', 'v', '4', '9'));
- _insert_feature("character_variant_50", HB_TAG('c', 'v', '5', '0'));
- _insert_feature("character_variant_51", HB_TAG('c', 'v', '5', '1'));
- _insert_feature("character_variant_52", HB_TAG('c', 'v', '5', '2'));
- _insert_feature("character_variant_53", HB_TAG('c', 'v', '5', '3'));
- _insert_feature("character_variant_54", HB_TAG('c', 'v', '5', '4'));
- _insert_feature("character_variant_55", HB_TAG('c', 'v', '5', '5'));
- _insert_feature("character_variant_56", HB_TAG('c', 'v', '5', '6'));
- _insert_feature("character_variant_57", HB_TAG('c', 'v', '5', '7'));
- _insert_feature("character_variant_58", HB_TAG('c', 'v', '5', '8'));
- _insert_feature("character_variant_59", HB_TAG('c', 'v', '5', '9'));
- _insert_feature("character_variant_60", HB_TAG('c', 'v', '6', '0'));
- _insert_feature("character_variant_61", HB_TAG('c', 'v', '6', '1'));
- _insert_feature("character_variant_62", HB_TAG('c', 'v', '6', '2'));
- _insert_feature("character_variant_63", HB_TAG('c', 'v', '6', '3'));
- _insert_feature("character_variant_64", HB_TAG('c', 'v', '6', '4'));
- _insert_feature("character_variant_65", HB_TAG('c', 'v', '6', '5'));
- _insert_feature("character_variant_66", HB_TAG('c', 'v', '6', '6'));
- _insert_feature("character_variant_67", HB_TAG('c', 'v', '6', '7'));
- _insert_feature("character_variant_68", HB_TAG('c', 'v', '6', '8'));
- _insert_feature("character_variant_69", HB_TAG('c', 'v', '6', '9'));
- _insert_feature("character_variant_70", HB_TAG('c', 'v', '7', '0'));
- _insert_feature("character_variant_71", HB_TAG('c', 'v', '7', '1'));
- _insert_feature("character_variant_72", HB_TAG('c', 'v', '7', '2'));
- _insert_feature("character_variant_73", HB_TAG('c', 'v', '7', '3'));
- _insert_feature("character_variant_74", HB_TAG('c', 'v', '7', '4'));
- _insert_feature("character_variant_75", HB_TAG('c', 'v', '7', '5'));
- _insert_feature("character_variant_76", HB_TAG('c', 'v', '7', '6'));
- _insert_feature("character_variant_77", HB_TAG('c', 'v', '7', '7'));
- _insert_feature("character_variant_78", HB_TAG('c', 'v', '7', '8'));
- _insert_feature("character_variant_79", HB_TAG('c', 'v', '7', '9'));
- _insert_feature("character_variant_80", HB_TAG('c', 'v', '8', '0'));
- _insert_feature("character_variant_81", HB_TAG('c', 'v', '8', '1'));
- _insert_feature("character_variant_82", HB_TAG('c', 'v', '8', '2'));
- _insert_feature("character_variant_83", HB_TAG('c', 'v', '8', '3'));
- _insert_feature("character_variant_84", HB_TAG('c', 'v', '8', '4'));
- _insert_feature("character_variant_85", HB_TAG('c', 'v', '8', '5'));
- _insert_feature("character_variant_86", HB_TAG('c', 'v', '8', '6'));
- _insert_feature("character_variant_87", HB_TAG('c', 'v', '8', '7'));
- _insert_feature("character_variant_88", HB_TAG('c', 'v', '8', '8'));
- _insert_feature("character_variant_89", HB_TAG('c', 'v', '8', '9'));
- _insert_feature("character_variant_90", HB_TAG('c', 'v', '9', '0'));
- _insert_feature("character_variant_91", HB_TAG('c', 'v', '9', '1'));
- _insert_feature("character_variant_92", HB_TAG('c', 'v', '9', '2'));
- _insert_feature("character_variant_93", HB_TAG('c', 'v', '9', '3'));
- _insert_feature("character_variant_94", HB_TAG('c', 'v', '9', '4'));
- _insert_feature("character_variant_95", HB_TAG('c', 'v', '9', '5'));
- _insert_feature("character_variant_96", HB_TAG('c', 'v', '9', '6'));
- _insert_feature("character_variant_97", HB_TAG('c', 'v', '9', '7'));
- _insert_feature("character_variant_98", HB_TAG('c', 'v', '9', '8'));
- _insert_feature("character_variant_99", HB_TAG('c', 'v', '9', '9'));
- _insert_feature("petite_capitals_from_capitals", HB_TAG('c', '2', 'p', 'c'));
- _insert_feature("small_capitals_from_capitals", HB_TAG('c', '2', 's', 'c'));
- _insert_feature("distances", HB_TAG('d', 'i', 's', 't'));
- _insert_feature("discretionary_ligatures", HB_TAG('d', 'l', 'i', 'g'));
- _insert_feature("denominators", HB_TAG('d', 'n', 'o', 'm'));
- _insert_feature("dotless_forms", HB_TAG('d', 't', 'l', 's'));
- _insert_feature("expert_forms", HB_TAG('e', 'x', 'p', 't'));
- _insert_feature("final_glyph_on_line_alternates", HB_TAG('f', 'a', 'l', 't'));
- _insert_feature("terminal_forms_2", HB_TAG('f', 'i', 'n', '2'));
- _insert_feature("terminal_forms_3", HB_TAG('f', 'i', 'n', '3'));
- _insert_feature("terminal_forms", HB_TAG('f', 'i', 'n', 'a'));
- _insert_feature("flattened_accent_forms", HB_TAG('f', 'l', 'a', 'c'));
- _insert_feature("fractions", HB_TAG('f', 'r', 'a', 'c'));
- _insert_feature("full_widths", HB_TAG('f', 'w', 'i', 'd'));
- _insert_feature("half_forms", HB_TAG('h', 'a', 'l', 'f'));
- _insert_feature("halant_forms", HB_TAG('h', 'a', 'l', 'n'));
- _insert_feature("alternate_half_widths", HB_TAG('h', 'a', 'l', 't'));
- _insert_feature("historical_forms", HB_TAG('h', 'i', 's', 't'));
- _insert_feature("horizontal_kana_alternates", HB_TAG('h', 'k', 'n', 'a'));
- _insert_feature("historical_ligatures", HB_TAG('h', 'l', 'i', 'g'));
- _insert_feature("hangul", HB_TAG('h', 'n', 'g', 'l'));
- _insert_feature("hojo_kanji_forms", HB_TAG('h', 'o', 'j', 'o'));
- _insert_feature("half_widths", HB_TAG('h', 'w', 'i', 'd'));
- _insert_feature("initial_forms", HB_TAG('i', 'n', 'i', 't'));
- _insert_feature("isolated_forms", HB_TAG('i', 's', 'o', 'l'));
- _insert_feature("italics", HB_TAG('i', 't', 'a', 'l'));
- _insert_feature("justification_alternates", HB_TAG('j', 'a', 'l', 't'));
- _insert_feature("jis78_forms", HB_TAG('j', 'p', '7', '8'));
- _insert_feature("jis83_forms", HB_TAG('j', 'p', '8', '3'));
- _insert_feature("jis90_forms", HB_TAG('j', 'p', '9', '0'));
- _insert_feature("jis2004_forms", HB_TAG('j', 'p', '0', '4'));
- _insert_feature("kerning", HB_TAG('k', 'e', 'r', 'n'));
- _insert_feature("left_bounds", HB_TAG('l', 'f', 'b', 'd'));
- _insert_feature("standard_ligatures", HB_TAG('l', 'i', 'g', 'a'));
- _insert_feature("leading_jamo_forms", HB_TAG('l', 'j', 'm', 'o'));
- _insert_feature("lining_figures", HB_TAG('l', 'n', 'u', 'm'));
- _insert_feature("localized_forms", HB_TAG('l', 'o', 'c', 'l'));
- _insert_feature("left_to_right_alternates", HB_TAG('l', 't', 'r', 'a'));
- _insert_feature("left_to_right_mirrored_forms", HB_TAG('l', 't', 'r', 'm'));
- _insert_feature("mark_positioning", HB_TAG('m', 'a', 'r', 'k'));
- _insert_feature("medial_forms_2", HB_TAG('m', 'e', 'd', '2'));
- _insert_feature("medial_forms", HB_TAG('m', 'e', 'd', 'i'));
- _insert_feature("mathematical_greek", HB_TAG('m', 'g', 'r', 'k'));
- _insert_feature("mark_to_mark_positioning", HB_TAG('m', 'k', 'm', 'k'));
- _insert_feature("mark_positioning_via_substitution", HB_TAG('m', 's', 'e', 't'));
- _insert_feature("alternate_annotation_forms", HB_TAG('n', 'a', 'l', 't'));
- _insert_feature("nlc_kanji_forms", HB_TAG('n', 'l', 'c', 'k'));
- _insert_feature("nukta_forms", HB_TAG('n', 'u', 'k', 't'));
- _insert_feature("numerators", HB_TAG('n', 'u', 'm', 'r'));
- _insert_feature("oldstyle_figures", HB_TAG('o', 'n', 'u', 'm'));
- _insert_feature("optical_bounds", HB_TAG('o', 'p', 'b', 'd'));
- _insert_feature("ordinals", HB_TAG('o', 'r', 'd', 'n'));
- _insert_feature("ornaments", HB_TAG('o', 'r', 'n', 'm'));
- _insert_feature("proportional_alternate_widths", HB_TAG('p', 'a', 'l', 't'));
- _insert_feature("petite_capitals", HB_TAG('p', 'c', 'a', 'p'));
- _insert_feature("proportional_kana", HB_TAG('p', 'k', 'n', 'a'));
- _insert_feature("proportional_figures", HB_TAG('p', 'n', 'u', 'm'));
- _insert_feature("pre_base_forms", HB_TAG('p', 'r', 'e', 'f'));
- _insert_feature("pre_base_substitutions", HB_TAG('p', 'r', 'e', 's'));
- _insert_feature("post_base_forms", HB_TAG('p', 's', 't', 'f'));
- _insert_feature("post_base_substitutions", HB_TAG('p', 's', 't', 's'));
- _insert_feature("proportional_widths", HB_TAG('p', 'w', 'i', 'd'));
- _insert_feature("quarter_widths", HB_TAG('q', 'w', 'i', 'd'));
- _insert_feature("randomize", HB_TAG('r', 'a', 'n', 'd'));
- _insert_feature("required_contextual_alternates", HB_TAG('r', 'c', 'l', 't'));
- _insert_feature("rakar_forms", HB_TAG('r', 'k', 'r', 'f'));
- _insert_feature("required_ligatures", HB_TAG('r', 'l', 'i', 'g'));
- _insert_feature("reph_forms", HB_TAG('r', 'p', 'h', 'f'));
- _insert_feature("right_bounds", HB_TAG('r', 't', 'b', 'd'));
- _insert_feature("right_to_left_alternates", HB_TAG('r', 't', 'l', 'a'));
- _insert_feature("right_to_left_mirrored_forms", HB_TAG('r', 't', 'l', 'm'));
- _insert_feature("ruby_notation_forms", HB_TAG('r', 'u', 'b', 'y'));
- _insert_feature("required_variation_alternates", HB_TAG('r', 'v', 'r', 'n'));
- _insert_feature("stylistic_alternates", HB_TAG('s', 'a', 'l', 't'));
- _insert_feature("scientific_inferiors", HB_TAG('s', 'i', 'n', 'f'));
- _insert_feature("optical_size", HB_TAG('s', 'i', 'z', 'e'));
- _insert_feature("small_capitals", HB_TAG('s', 'm', 'c', 'p'));
- _insert_feature("simplified_forms", HB_TAG('s', 'm', 'p', 'l'));
- _insert_feature("stylistic_set_01", HB_TAG('s', 's', '0', '1'));
- _insert_feature("stylistic_set_02", HB_TAG('s', 's', '0', '2'));
- _insert_feature("stylistic_set_03", HB_TAG('s', 's', '0', '3'));
- _insert_feature("stylistic_set_04", HB_TAG('s', 's', '0', '4'));
- _insert_feature("stylistic_set_05", HB_TAG('s', 's', '0', '5'));
- _insert_feature("stylistic_set_06", HB_TAG('s', 's', '0', '6'));
- _insert_feature("stylistic_set_07", HB_TAG('s', 's', '0', '7'));
- _insert_feature("stylistic_set_08", HB_TAG('s', 's', '0', '8'));
- _insert_feature("stylistic_set_09", HB_TAG('s', 's', '0', '9'));
- _insert_feature("stylistic_set_10", HB_TAG('s', 's', '1', '0'));
- _insert_feature("stylistic_set_11", HB_TAG('s', 's', '1', '1'));
- _insert_feature("stylistic_set_12", HB_TAG('s', 's', '1', '2'));
- _insert_feature("stylistic_set_13", HB_TAG('s', 's', '1', '3'));
- _insert_feature("stylistic_set_14", HB_TAG('s', 's', '1', '4'));
- _insert_feature("stylistic_set_15", HB_TAG('s', 's', '1', '5'));
- _insert_feature("stylistic_set_16", HB_TAG('s', 's', '1', '6'));
- _insert_feature("stylistic_set_17", HB_TAG('s', 's', '1', '7'));
- _insert_feature("stylistic_set_18", HB_TAG('s', 's', '1', '8'));
- _insert_feature("stylistic_set_19", HB_TAG('s', 's', '1', '9'));
- _insert_feature("stylistic_set_20", HB_TAG('s', 's', '2', '0'));
- _insert_feature("math_script_style_alternates", HB_TAG('s', 's', 't', 'y'));
- _insert_feature("stretching_glyph_decomposition", HB_TAG('s', 't', 'c', 'h'));
- _insert_feature("subscript", HB_TAG('s', 'u', 'b', 's'));
- _insert_feature("superscript", HB_TAG('s', 'u', 'p', 's'));
- _insert_feature("swash", HB_TAG('s', 'w', 's', 'h'));
- _insert_feature("titling", HB_TAG('t', 'i', 't', 'l'));
- _insert_feature("trailing_jamo_forms", HB_TAG('t', 'j', 'm', 'o'));
- _insert_feature("traditional_name_forms", HB_TAG('t', 'n', 'a', 'm'));
- _insert_feature("tabular_figures", HB_TAG('t', 'n', 'u', 'm'));
- _insert_feature("traditional_forms", HB_TAG('t', 'r', 'a', 'd'));
- _insert_feature("third_widths", HB_TAG('t', 'w', 'i', 'd'));
- _insert_feature("unicase", HB_TAG('u', 'n', 'i', 'c'));
- _insert_feature("alternate_vertical_metrics", HB_TAG('v', 'a', 'l', 't'));
- _insert_feature("vattu_variants", HB_TAG('v', 'a', 't', 'u'));
- _insert_feature("vertical_writing", HB_TAG('v', 'e', 'r', 't'));
- _insert_feature("alternate_vertical_half_metrics", HB_TAG('v', 'h', 'a', 'l'));
- _insert_feature("vowel_jamo_forms", HB_TAG('v', 'j', 'm', 'o'));
- _insert_feature("vertical_kana_alternates", HB_TAG('v', 'k', 'n', 'a'));
- _insert_feature("vertical_kerning", HB_TAG('v', 'k', 'r', 'n'));
- _insert_feature("proportional_alternate_vertical_metrics", HB_TAG('v', 'p', 'a', 'l'));
- _insert_feature("vertical_alternates_and_rotation", HB_TAG('v', 'r', 't', '2'));
- _insert_feature("vertical_alternates_for_rotation", HB_TAG('v', 'r', 't', 'r'));
- _insert_feature("slashed_zero", HB_TAG('z', 'e', 'r', 'o'));
+ // Name, Tag, Data Type, Hidden
+ _insert_feature("access_all_alternates", HB_TAG('a', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("above_base_forms", HB_TAG('a', 'b', 'v', 'f'), Variant::Type::INT, true);
+ _insert_feature("above_base_mark_positioning", HB_TAG('a', 'b', 'v', 'm'), Variant::Type::INT, true);
+ _insert_feature("above_base_substitutions", HB_TAG('a', 'b', 'v', 's'), Variant::Type::INT, true);
+ _insert_feature("alternative_fractions", HB_TAG('a', 'f', 'r', 'c'), Variant::Type::INT, false);
+ _insert_feature("akhands", HB_TAG('a', 'k', 'h', 'n'), Variant::Type::INT, true);
+ _insert_feature("below_base_forms", HB_TAG('b', 'l', 'w', 'f'), Variant::Type::INT, true);
+ _insert_feature("below_base_mark_positioning", HB_TAG('b', 'l', 'w', 'm'), Variant::Type::INT, true);
+ _insert_feature("below_base_substitutions", HB_TAG('b', 'l', 'w', 's'), Variant::Type::INT, true);
+ _insert_feature("contextual_alternates", HB_TAG('c', 'a', 'l', 't'), Variant::Type::BOOL, false);
+ _insert_feature("case_sensitive_forms", HB_TAG('c', 'a', 's', 'e'), Variant::Type::BOOL, false);
+ _insert_feature("glyph_composition", HB_TAG('c', 'c', 'm', 'p'), Variant::Type::INT, true);
+ _insert_feature("conjunct_form_after_ro", HB_TAG('c', 'f', 'a', 'r'), Variant::Type::INT, true);
+ _insert_feature("contextual_half_width_spacing", HB_TAG('c', 'h', 'w', 's'), Variant::Type::INT, true);
+ _insert_feature("conjunct_forms", HB_TAG('c', 'j', 'c', 't'), Variant::Type::INT, true);
+ _insert_feature("contextual_ligatures", HB_TAG('c', 'l', 'i', 'g'), Variant::Type::BOOL, false);
+ _insert_feature("centered_cjk_punctuation", HB_TAG('c', 'p', 'c', 't'), Variant::Type::BOOL, false);
+ _insert_feature("capital_spacing", HB_TAG('c', 'p', 's', 'p'), Variant::Type::BOOL, false);
+ _insert_feature("contextual_swash", HB_TAG('c', 's', 'w', 'h'), Variant::Type::INT, false);
+ _insert_feature("cursive_positioning", HB_TAG('c', 'u', 'r', 's'), Variant::Type::INT, true);
+ _insert_feature("character_variant_01", HB_TAG('c', 'v', '0', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_02", HB_TAG('c', 'v', '0', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_03", HB_TAG('c', 'v', '0', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_04", HB_TAG('c', 'v', '0', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_05", HB_TAG('c', 'v', '0', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_06", HB_TAG('c', 'v', '0', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_07", HB_TAG('c', 'v', '0', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_08", HB_TAG('c', 'v', '0', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_09", HB_TAG('c', 'v', '0', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_10", HB_TAG('c', 'v', '1', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_11", HB_TAG('c', 'v', '1', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_12", HB_TAG('c', 'v', '1', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_13", HB_TAG('c', 'v', '1', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_14", HB_TAG('c', 'v', '1', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_15", HB_TAG('c', 'v', '1', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_16", HB_TAG('c', 'v', '1', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_17", HB_TAG('c', 'v', '1', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_18", HB_TAG('c', 'v', '1', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_19", HB_TAG('c', 'v', '1', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_20", HB_TAG('c', 'v', '2', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_21", HB_TAG('c', 'v', '2', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_22", HB_TAG('c', 'v', '2', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_23", HB_TAG('c', 'v', '2', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_24", HB_TAG('c', 'v', '2', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_25", HB_TAG('c', 'v', '2', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_26", HB_TAG('c', 'v', '2', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_27", HB_TAG('c', 'v', '2', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_28", HB_TAG('c', 'v', '2', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_29", HB_TAG('c', 'v', '2', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_30", HB_TAG('c', 'v', '3', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_31", HB_TAG('c', 'v', '3', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_32", HB_TAG('c', 'v', '3', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_33", HB_TAG('c', 'v', '3', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_34", HB_TAG('c', 'v', '3', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_35", HB_TAG('c', 'v', '3', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_36", HB_TAG('c', 'v', '3', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_37", HB_TAG('c', 'v', '3', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_38", HB_TAG('c', 'v', '3', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_39", HB_TAG('c', 'v', '3', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_40", HB_TAG('c', 'v', '4', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_41", HB_TAG('c', 'v', '4', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_42", HB_TAG('c', 'v', '4', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_43", HB_TAG('c', 'v', '4', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_44", HB_TAG('c', 'v', '4', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_45", HB_TAG('c', 'v', '4', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_46", HB_TAG('c', 'v', '4', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_47", HB_TAG('c', 'v', '4', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_48", HB_TAG('c', 'v', '4', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_49", HB_TAG('c', 'v', '4', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_50", HB_TAG('c', 'v', '5', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_51", HB_TAG('c', 'v', '5', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_52", HB_TAG('c', 'v', '5', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_53", HB_TAG('c', 'v', '5', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_54", HB_TAG('c', 'v', '5', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_55", HB_TAG('c', 'v', '5', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_56", HB_TAG('c', 'v', '5', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_57", HB_TAG('c', 'v', '5', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_58", HB_TAG('c', 'v', '5', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_59", HB_TAG('c', 'v', '5', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_60", HB_TAG('c', 'v', '6', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_61", HB_TAG('c', 'v', '6', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_62", HB_TAG('c', 'v', '6', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_63", HB_TAG('c', 'v', '6', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_64", HB_TAG('c', 'v', '6', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_65", HB_TAG('c', 'v', '6', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_66", HB_TAG('c', 'v', '6', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_67", HB_TAG('c', 'v', '6', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_68", HB_TAG('c', 'v', '6', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_69", HB_TAG('c', 'v', '6', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_70", HB_TAG('c', 'v', '7', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_71", HB_TAG('c', 'v', '7', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_72", HB_TAG('c', 'v', '7', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_73", HB_TAG('c', 'v', '7', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_74", HB_TAG('c', 'v', '7', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_75", HB_TAG('c', 'v', '7', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_76", HB_TAG('c', 'v', '7', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_77", HB_TAG('c', 'v', '7', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_78", HB_TAG('c', 'v', '7', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_79", HB_TAG('c', 'v', '7', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_80", HB_TAG('c', 'v', '8', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_81", HB_TAG('c', 'v', '8', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_82", HB_TAG('c', 'v', '8', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_83", HB_TAG('c', 'v', '8', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_84", HB_TAG('c', 'v', '8', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_85", HB_TAG('c', 'v', '8', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_86", HB_TAG('c', 'v', '8', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_87", HB_TAG('c', 'v', '8', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_88", HB_TAG('c', 'v', '8', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_89", HB_TAG('c', 'v', '8', '9'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_90", HB_TAG('c', 'v', '9', '0'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_91", HB_TAG('c', 'v', '9', '1'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_92", HB_TAG('c', 'v', '9', '2'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_93", HB_TAG('c', 'v', '9', '3'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_94", HB_TAG('c', 'v', '9', '4'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_95", HB_TAG('c', 'v', '9', '5'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_96", HB_TAG('c', 'v', '9', '6'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_97", HB_TAG('c', 'v', '9', '7'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_98", HB_TAG('c', 'v', '9', '8'), Variant::Type::BOOL, false);
+ _insert_feature("character_variant_99", HB_TAG('c', 'v', '9', '9'), Variant::Type::BOOL, false);
+ _insert_feature("petite_capitals_from_capitals", HB_TAG('c', '2', 'p', 'c'), Variant::Type::BOOL, false);
+ _insert_feature("small_capitals_from_capitals", HB_TAG('c', '2', 's', 'c'), Variant::Type::BOOL, false);
+ _insert_feature("distances", HB_TAG('d', 'i', 's', 't'), Variant::Type::INT, true);
+ _insert_feature("discretionary_ligatures", HB_TAG('d', 'l', 'i', 'g'), Variant::Type::BOOL, false);
+ _insert_feature("denominators", HB_TAG('d', 'n', 'o', 'm'), Variant::Type::BOOL, false);
+ _insert_feature("dotless_forms", HB_TAG('d', 't', 'l', 's'), Variant::Type::INT, true);
+ _insert_feature("expert_forms", HB_TAG('e', 'x', 'p', 't'), Variant::Type::BOOL, true);
+ _insert_feature("final_glyph_on_line_alternates", HB_TAG('f', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("terminal_forms_2", HB_TAG('f', 'i', 'n', '2'), Variant::Type::INT, true);
+ _insert_feature("terminal_forms_3", HB_TAG('f', 'i', 'n', '3'), Variant::Type::INT, true);
+ _insert_feature("terminal_forms", HB_TAG('f', 'i', 'n', 'a'), Variant::Type::INT, true);
+ _insert_feature("flattened_accent_forms", HB_TAG('f', 'l', 'a', 'c'), Variant::Type::INT, true);
+ _insert_feature("fractions", HB_TAG('f', 'r', 'a', 'c'), Variant::Type::BOOL, false);
+ _insert_feature("full_widths", HB_TAG('f', 'w', 'i', 'd'), Variant::Type::BOOL, false);
+ _insert_feature("half_forms", HB_TAG('h', 'a', 'l', 'f'), Variant::Type::INT, true);
+ _insert_feature("halant_forms", HB_TAG('h', 'a', 'l', 'n'), Variant::Type::INT, true);
+ _insert_feature("alternate_half_widths", HB_TAG('h', 'a', 'l', 't'), Variant::Type::BOOL, false);
+ _insert_feature("historical_forms", HB_TAG('h', 'i', 's', 't'), Variant::Type::INT, false);
+ _insert_feature("horizontal_kana_alternates", HB_TAG('h', 'k', 'n', 'a'), Variant::Type::BOOL, false);
+ _insert_feature("historical_ligatures", HB_TAG('h', 'l', 'i', 'g'), Variant::Type::BOOL, false);
+ _insert_feature("hangul", HB_TAG('h', 'n', 'g', 'l'), Variant::Type::INT, false);
+ _insert_feature("hojo_kanji_forms", HB_TAG('h', 'o', 'j', 'o'), Variant::Type::INT, false);
+ _insert_feature("half_widths", HB_TAG('h', 'w', 'i', 'd'), Variant::Type::BOOL, false);
+ _insert_feature("initial_forms", HB_TAG('i', 'n', 'i', 't'), Variant::Type::INT, true);
+ _insert_feature("isolated_forms", HB_TAG('i', 's', 'o', 'l'), Variant::Type::INT, true);
+ _insert_feature("italics", HB_TAG('i', 't', 'a', 'l'), Variant::Type::INT, false);
+ _insert_feature("justification_alternates", HB_TAG('j', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("jis78_forms", HB_TAG('j', 'p', '7', '8'), Variant::Type::INT, false);
+ _insert_feature("jis83_forms", HB_TAG('j', 'p', '8', '3'), Variant::Type::INT, false);
+ _insert_feature("jis90_forms", HB_TAG('j', 'p', '9', '0'), Variant::Type::INT, false);
+ _insert_feature("jis2004_forms", HB_TAG('j', 'p', '0', '4'), Variant::Type::INT, false);
+ _insert_feature("kerning", HB_TAG('k', 'e', 'r', 'n'), Variant::Type::BOOL, false);
+ _insert_feature("left_bounds", HB_TAG('l', 'f', 'b', 'd'), Variant::Type::INT, false);
+ _insert_feature("standard_ligatures", HB_TAG('l', 'i', 'g', 'a'), Variant::Type::BOOL, false);
+ _insert_feature("leading_jamo_forms", HB_TAG('l', 'j', 'm', 'o'), Variant::Type::INT, true);
+ _insert_feature("lining_figures", HB_TAG('l', 'n', 'u', 'm'), Variant::Type::INT, false);
+ _insert_feature("localized_forms", HB_TAG('l', 'o', 'c', 'l'), Variant::Type::INT, true);
+ _insert_feature("left_to_right_alternates", HB_TAG('l', 't', 'r', 'a'), Variant::Type::INT, true);
+ _insert_feature("left_to_right_mirrored_forms", HB_TAG('l', 't', 'r', 'm'), Variant::Type::INT, true);
+ _insert_feature("mark_positioning", HB_TAG('m', 'a', 'r', 'k'), Variant::Type::INT, true);
+ _insert_feature("medial_forms_2", HB_TAG('m', 'e', 'd', '2'), Variant::Type::INT, true);
+ _insert_feature("medial_forms", HB_TAG('m', 'e', 'd', 'i'), Variant::Type::INT, true);
+ _insert_feature("mathematical_greek", HB_TAG('m', 'g', 'r', 'k'), Variant::Type::BOOL, false);
+ _insert_feature("mark_to_mark_positioning", HB_TAG('m', 'k', 'm', 'k'), Variant::Type::INT, true);
+ _insert_feature("mark_positioning_via_substitution", HB_TAG('m', 's', 'e', 't'), Variant::Type::INT, true);
+ _insert_feature("alternate_annotation_forms", HB_TAG('n', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("nlc_kanji_forms", HB_TAG('n', 'l', 'c', 'k'), Variant::Type::INT, false);
+ _insert_feature("nukta_forms", HB_TAG('n', 'u', 'k', 't'), Variant::Type::INT, true);
+ _insert_feature("numerators", HB_TAG('n', 'u', 'm', 'r'), Variant::Type::BOOL, false);
+ _insert_feature("oldstyle_figures", HB_TAG('o', 'n', 'u', 'm'), Variant::Type::INT, false);
+ _insert_feature("optical_bounds", HB_TAG('o', 'p', 'b', 'd'), Variant::Type::INT, true);
+ _insert_feature("ordinals", HB_TAG('o', 'r', 'd', 'n'), Variant::Type::BOOL, false);
+ _insert_feature("ornaments", HB_TAG('o', 'r', 'n', 'm'), Variant::Type::INT, false);
+ _insert_feature("proportional_alternate_widths", HB_TAG('p', 'a', 'l', 't'), Variant::Type::BOOL, false);
+ _insert_feature("petite_capitals", HB_TAG('p', 'c', 'a', 'p'), Variant::Type::BOOL, false);
+ _insert_feature("proportional_kana", HB_TAG('p', 'k', 'n', 'a'), Variant::Type::BOOL, false);
+ _insert_feature("proportional_figures", HB_TAG('p', 'n', 'u', 'm'), Variant::Type::BOOL, false);
+ _insert_feature("pre_base_forms", HB_TAG('p', 'r', 'e', 'f'), Variant::Type::INT, true);
+ _insert_feature("pre_base_substitutions", HB_TAG('p', 'r', 'e', 's'), Variant::Type::INT, true);
+ _insert_feature("post_base_forms", HB_TAG('p', 's', 't', 'f'), Variant::Type::INT, true);
+ _insert_feature("post_base_substitutions", HB_TAG('p', 's', 't', 's'), Variant::Type::INT, true);
+ _insert_feature("proportional_widths", HB_TAG('p', 'w', 'i', 'd'), Variant::Type::BOOL, false);
+ _insert_feature("quarter_widths", HB_TAG('q', 'w', 'i', 'd'), Variant::Type::BOOL, false);
+ _insert_feature("randomize", HB_TAG('r', 'a', 'n', 'd'), Variant::Type::INT, false);
+ _insert_feature("required_contextual_alternates", HB_TAG('r', 'c', 'l', 't'), Variant::Type::BOOL, true);
+ _insert_feature("rakar_forms", HB_TAG('r', 'k', 'r', 'f'), Variant::Type::INT, true);
+ _insert_feature("required_ligatures", HB_TAG('r', 'l', 'i', 'g'), Variant::Type::BOOL, true);
+ _insert_feature("reph_forms", HB_TAG('r', 'p', 'h', 'f'), Variant::Type::INT, true);
+ _insert_feature("right_bounds", HB_TAG('r', 't', 'b', 'd'), Variant::Type::INT, false);
+ _insert_feature("right_to_left_alternates", HB_TAG('r', 't', 'l', 'a'), Variant::Type::INT, true);
+ _insert_feature("right_to_left_mirrored_forms", HB_TAG('r', 't', 'l', 'm'), Variant::Type::INT, true);
+ _insert_feature("ruby_notation_forms", HB_TAG('r', 'u', 'b', 'y'), Variant::Type::INT, false);
+ _insert_feature("required_variation_alternates", HB_TAG('r', 'v', 'r', 'n'), Variant::Type::INT, true);
+ _insert_feature("stylistic_alternates", HB_TAG('s', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("scientific_inferiors", HB_TAG('s', 'i', 'n', 'f'), Variant::Type::BOOL, false);
+ _insert_feature("optical_size", HB_TAG('s', 'i', 'z', 'e'), Variant::Type::INT, false);
+ _insert_feature("small_capitals", HB_TAG('s', 'm', 'c', 'p'), Variant::Type::BOOL, false);
+ _insert_feature("simplified_forms", HB_TAG('s', 'm', 'p', 'l'), Variant::Type::INT, false);
+ _insert_feature("stylistic_set_01", HB_TAG('s', 's', '0', '1'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_02", HB_TAG('s', 's', '0', '2'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_03", HB_TAG('s', 's', '0', '3'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_04", HB_TAG('s', 's', '0', '4'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_05", HB_TAG('s', 's', '0', '5'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_06", HB_TAG('s', 's', '0', '6'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_07", HB_TAG('s', 's', '0', '7'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_08", HB_TAG('s', 's', '0', '8'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_09", HB_TAG('s', 's', '0', '9'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_10", HB_TAG('s', 's', '1', '0'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_11", HB_TAG('s', 's', '1', '1'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_12", HB_TAG('s', 's', '1', '2'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_13", HB_TAG('s', 's', '1', '3'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_14", HB_TAG('s', 's', '1', '4'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_15", HB_TAG('s', 's', '1', '5'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_16", HB_TAG('s', 's', '1', '6'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_17", HB_TAG('s', 's', '1', '7'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_18", HB_TAG('s', 's', '1', '8'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_19", HB_TAG('s', 's', '1', '9'), Variant::Type::BOOL, false);
+ _insert_feature("stylistic_set_20", HB_TAG('s', 's', '2', '0'), Variant::Type::BOOL, false);
+ _insert_feature("math_script_style_alternates", HB_TAG('s', 's', 't', 'y'), Variant::Type::INT, true);
+ _insert_feature("stretching_glyph_decomposition", HB_TAG('s', 't', 'c', 'h'), Variant::Type::INT, true);
+ _insert_feature("subscript", HB_TAG('s', 'u', 'b', 's'), Variant::Type::BOOL, false);
+ _insert_feature("superscript", HB_TAG('s', 'u', 'p', 's'), Variant::Type::BOOL, false);
+ _insert_feature("swash", HB_TAG('s', 'w', 's', 'h'), Variant::Type::INT, false);
+ _insert_feature("titling", HB_TAG('t', 'i', 't', 'l'), Variant::Type::BOOL, false);
+ _insert_feature("trailing_jamo_forms", HB_TAG('t', 'j', 'm', 'o'), Variant::Type::INT, true);
+ _insert_feature("traditional_name_forms", HB_TAG('t', 'n', 'a', 'm'), Variant::Type::INT, false);
+ _insert_feature("tabular_figures", HB_TAG('t', 'n', 'u', 'm'), Variant::Type::BOOL, false);
+ _insert_feature("traditional_forms", HB_TAG('t', 'r', 'a', 'd'), Variant::Type::INT, false);
+ _insert_feature("third_widths", HB_TAG('t', 'w', 'i', 'd'), Variant::Type::BOOL, false);
+ _insert_feature("unicase", HB_TAG('u', 'n', 'i', 'c'), Variant::Type::BOOL, false);
+ _insert_feature("alternate_vertical_metrics", HB_TAG('v', 'a', 'l', 't'), Variant::Type::INT, false);
+ _insert_feature("vattu_variants", HB_TAG('v', 'a', 't', 'u'), Variant::Type::INT, true);
+ _insert_feature("vertical_contextual_half_width_spacing", HB_TAG('v', 'c', 'h', 'w'), Variant::Type::BOOL, false);
+ _insert_feature("vertical_alternates", HB_TAG('v', 'e', 'r', 't'), Variant::Type::INT, false);
+ _insert_feature("alternate_vertical_half_metrics", HB_TAG('v', 'h', 'a', 'l'), Variant::Type::BOOL, false);
+ _insert_feature("vowel_jamo_forms", HB_TAG('v', 'j', 'm', 'o'), Variant::Type::INT, true);
+ _insert_feature("vertical_kana_alternates", HB_TAG('v', 'k', 'n', 'a'), Variant::Type::INT, false);
+ _insert_feature("vertical_kerning", HB_TAG('v', 'k', 'r', 'n'), Variant::Type::BOOL, false);
+ _insert_feature("proportional_alternate_vertical_metrics", HB_TAG('v', 'p', 'a', 'l'), Variant::Type::BOOL, false);
+ _insert_feature("vertical_alternates_and_rotation", HB_TAG('v', 'r', 't', '2'), Variant::Type::INT, false);
+ _insert_feature("vertical_alternates_for_rotation", HB_TAG('v', 'r', 't', 'r'), Variant::Type::INT, false);
+ _insert_feature("slashed_zero", HB_TAG('z', 'e', 'r', 'o'), Variant::Type::BOOL, false);
// Registered OpenType variation tag.
- _insert_feature("italic", HB_TAG('i', 't', 'a', 'l'));
- _insert_feature("optical_size", HB_TAG('o', 'p', 's', 'z'));
- _insert_feature("slant", HB_TAG('s', 'l', 'n', 't'));
- _insert_feature("width", HB_TAG('w', 'd', 't', 'h'));
- _insert_feature("weight", HB_TAG('w', 'g', 'h', 't'));
+ _insert_feature("italic", HB_TAG('i', 't', 'a', 'l'), Variant::Type::INT, false);
+ _insert_feature("optical_size", HB_TAG('o', 'p', 's', 'z'), Variant::Type::INT, false);
+ _insert_feature("slant", HB_TAG('s', 'l', 'n', 't'), Variant::Type::INT, false);
+ _insert_feature("width", HB_TAG('w', 'd', 't', 'h'), Variant::Type::INT, false);
+ _insert_feature("weight", HB_TAG('w', 'g', 'h', 't'), Variant::Type::INT, false);
}
int64_t TextServerAdvanced::name_to_tag(const String &p_name) const {
@@ -740,9 +748,23 @@ int64_t TextServerAdvanced::name_to_tag(const String &p_name) const {
return hb_tag_from_string(p_name.replace("custom_", "").ascii().get_data(), -1);
}
+Variant::Type TextServerAdvanced::_get_tag_type(int64_t p_tag) const {
+ if (feature_sets_inv.has(p_tag)) {
+ return feature_sets_inv[p_tag].vtype;
+ }
+ return Variant::Type::INT;
+}
+
+bool TextServerAdvanced::_get_tag_hidden(int64_t p_tag) const {
+ if (feature_sets_inv.has(p_tag)) {
+ return feature_sets_inv[p_tag].hidden;
+ }
+ return false;
+}
+
String TextServerAdvanced::tag_to_name(int64_t p_tag) const {
if (feature_sets_inv.has(p_tag)) {
- return feature_sets_inv[p_tag];
+ return feature_sets_inv[p_tag].name;
}
// No readable name, use tag string.
@@ -756,7 +778,7 @@ String TextServerAdvanced::tag_to_name(int64_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
+_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -953,7 +975,7 @@ void TextServerAdvanced::_generateMTSDF_threaded(uint32_t y, void *p_td) const {
}
}
-_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const {
+_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const {
msdfgen::Shape shape;
shape.contours.clear();
@@ -1059,7 +1081,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
#endif
#ifdef MODULE_FREETYPE_ENABLED
-_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontDataForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const {
+_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const {
int w = bitmap.width;
int h = bitmap.rows;
@@ -1136,12 +1158,12 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
/* Font Cache */
/*************************************************************************/
-_FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
+_FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false);
int32_t glyph_index = p_glyph & 0xffffff; // Remove subpixel shifts.
- FontDataForSizeAdvanced *fd = p_font_data->cache[p_size];
+ FontForSizeAdvanced *fd = p_font_data->cache[p_size];
if (fd->glyph_map.has(p_glyph)) {
return fd->glyph_map[p_glyph].found;
}
@@ -1260,13 +1282,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
return false;
}
-_FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const {
+_FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *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;
}
- FontDataForSizeAdvanced *fd = memnew(FontDataForSizeAdvanced);
+ FontForSizeAdvanced *fd = memnew(FontForSizeAdvanced);
fd->size = p_size;
if (p_font_data->data_ptr && (p_font_data->data_size > 0)) {
// Init dynamic font.
@@ -1358,21 +1380,23 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) {
p_font_data->style_flags |= FONT_FIXED_WIDTH;
}
+
+ hb_face_t *hb_face = hb_font_get_face(fd->hb_handle);
// Get supported scripts from OpenType font data.
p_font_data->supported_scripts.clear();
- unsigned int count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr);
+ unsigned int count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, nullptr, nullptr);
if (count != 0) {
hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t));
- hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, &count, script_tags);
+ hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, &count, script_tags);
for (unsigned int i = 0; i < count; i++) {
p_font_data->supported_scripts.insert(script_tags[i]);
}
memfree(script_tags);
}
- count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr);
+ count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GPOS, 0, nullptr, nullptr);
if (count != 0) {
hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t));
- hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, &count, script_tags);
+ hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GPOS, 0, &count, script_tags);
for (unsigned int i = 0; i < count; i++) {
p_font_data->supported_scripts.insert(script_tags[i]);
}
@@ -1596,21 +1620,47 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
// Read OpenType feature tags.
p_font_data->supported_features.clear();
- count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr);
+ count = hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GSUB, 0, nullptr, nullptr);
if (count != 0) {
hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t));
- hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, &count, feature_tags);
+ hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GSUB, 0, &count, feature_tags);
for (unsigned int i = 0; i < count; i++) {
- p_font_data->supported_features[feature_tags[i]] = 1;
+ Dictionary ftr;
+
+ hb_ot_name_id_t lbl_id;
+ if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GSUB, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) {
+ String lbl;
+ unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1;
+ lbl.resize(text_size);
+ hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw());
+ ftr["label"] = lbl;
+ }
+ ftr["type"] = _get_tag_type(feature_tags[i]);
+ ftr["hidden"] = _get_tag_hidden(feature_tags[i]);
+
+ p_font_data->supported_features[feature_tags[i]] = ftr;
}
memfree(feature_tags);
}
- count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr);
+ count = hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GPOS, 0, nullptr, nullptr);
if (count != 0) {
hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t));
- hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, &count, feature_tags);
+ hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GPOS, 0, &count, feature_tags);
for (unsigned int i = 0; i < count; i++) {
- p_font_data->supported_features[feature_tags[i]] = 1;
+ Dictionary ftr;
+
+ hb_ot_name_id_t lbl_id;
+ if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GPOS, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) {
+ String lbl;
+ unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1;
+ lbl.resize(text_size);
+ hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw());
+ ftr["label"] = lbl;
+ }
+ ftr["type"] = _get_tag_type(feature_tags[i]);
+ ftr["hidden"] = _get_tag_hidden(feature_tags[i]);
+
+ p_font_data->supported_features[feature_tags[i]] = ftr;
}
memfree(feature_tags);
}
@@ -1676,8 +1726,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced
return true;
}
-_FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_font_data) {
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : p_font_data->cache) {
+_FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) {
+ for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : p_font_data->cache) {
memdelete(E.value);
}
p_font_data->cache.clear();
@@ -1688,7 +1738,7 @@ _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_fo
}
hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, nullptr);
MutexLock lock(fd->mutex);
@@ -1702,13 +1752,13 @@ hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_
RID TextServerAdvanced::create_font() {
_THREAD_SAFE_METHOD_
- FontDataAdvanced *fd = memnew(FontDataAdvanced);
+ FontAdvanced *fd = memnew(FontAdvanced);
return font_owner.make_rid(fd);
}
void TextServerAdvanced::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1719,7 +1769,7 @@ void TextServerAdvanced::font_set_data(const RID &p_font_rid, const PackedByteAr
}
void TextServerAdvanced::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1733,7 +1783,7 @@ void TextServerAdvanced::font_set_face_index(const RID &p_font_rid, int64_t p_fa
ERR_FAIL_COND(p_face_index < 0);
ERR_FAIL_COND(p_face_index >= 0x7FFF);
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1744,7 +1794,7 @@ void TextServerAdvanced::font_set_face_index(const RID &p_font_rid, int64_t p_fa
}
int64_t TextServerAdvanced::font_get_face_index(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -1752,7 +1802,7 @@ int64_t TextServerAdvanced::font_get_face_index(const RID &p_font_rid) const {
}
int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -1793,7 +1843,7 @@ int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1803,7 +1853,7 @@ void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontSty
}
int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -1813,7 +1863,7 @@ int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid)
}
void TextServerAdvanced::font_set_style_name(const RID &p_font_rid, const String &p_name) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1823,7 +1873,7 @@ void TextServerAdvanced::font_set_style_name(const RID &p_font_rid, const String
}
String TextServerAdvanced::font_get_style_name(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
@@ -1833,7 +1883,7 @@ String TextServerAdvanced::font_get_style_name(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_name(const RID &p_font_rid, const String &p_name) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1843,7 +1893,7 @@ void TextServerAdvanced::font_set_name(const RID &p_font_rid, const String &p_na
}
String TextServerAdvanced::font_get_name(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
@@ -1853,7 +1903,7 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1864,7 +1914,7 @@ void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_anti
}
bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1872,12 +1922,12 @@ bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->mipmaps != p_generate_mipmaps) {
- for (KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) {
+ for (KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) {
for (int i = 0; i < E.value->textures.size(); i++) {
E.value->textures.write[i].dirty = true;
}
@@ -1887,7 +1937,7 @@ void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p
}
bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1895,7 +1945,7 @@ bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const
}
void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1906,7 +1956,7 @@ void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID &
}
bool TextServerAdvanced::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1914,7 +1964,7 @@ bool TextServerAdvanced::font_is_multichannel_signed_distance_field(const RID &p
}
void TextServerAdvanced::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1925,7 +1975,7 @@ void TextServerAdvanced::font_set_msdf_pixel_range(const RID &p_font_rid, int64_
}
int64_t TextServerAdvanced::font_get_msdf_pixel_range(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1933,7 +1983,7 @@ int64_t TextServerAdvanced::font_get_msdf_pixel_range(const RID &p_font_rid) con
}
void TextServerAdvanced::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1944,7 +1994,7 @@ void TextServerAdvanced::font_set_msdf_size(const RID &p_font_rid, int64_t p_msd
}
int64_t TextServerAdvanced::font_get_msdf_size(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1952,7 +2002,7 @@ int64_t TextServerAdvanced::font_get_msdf_size(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1960,7 +2010,7 @@ void TextServerAdvanced::font_set_fixed_size(const RID &p_font_rid, int64_t p_fi
}
int64_t TextServerAdvanced::font_get_fixed_size(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1968,7 +2018,7 @@ int64_t TextServerAdvanced::font_get_fixed_size(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1979,7 +2029,7 @@ void TextServerAdvanced::font_set_force_autohinter(const RID &p_font_rid, bool p
}
bool TextServerAdvanced::font_is_force_autohinter(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1987,7 +2037,7 @@ bool TextServerAdvanced::font_is_force_autohinter(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1998,7 +2048,7 @@ void TextServerAdvanced::font_set_hinting(const RID &p_font_rid, TextServer::Hin
}
TextServer::Hinting TextServerAdvanced::font_get_hinting(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, HINTING_NONE);
MutexLock lock(fd->mutex);
@@ -2006,7 +2056,7 @@ TextServer::Hinting TextServerAdvanced::font_get_hinting(const RID &p_font_rid)
}
void TextServerAdvanced::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2014,7 +2064,7 @@ void TextServerAdvanced::font_set_subpixel_positioning(const RID &p_font_rid, Te
}
TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positioning(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED);
MutexLock lock(fd->mutex);
@@ -2022,7 +2072,7 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin
}
void TextServerAdvanced::font_set_embolden(const RID &p_font_rid, double p_strength) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2033,7 +2083,7 @@ void TextServerAdvanced::font_set_embolden(const RID &p_font_rid, double p_stren
}
double TextServerAdvanced::font_get_embolden(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2041,7 +2091,7 @@ double TextServerAdvanced::font_get_embolden(const RID &p_font_rid) const {
}
void TextServerAdvanced::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2052,7 +2102,7 @@ void TextServerAdvanced::font_set_transform(const RID &p_font_rid, const Transfo
}
Transform2D TextServerAdvanced::font_get_transform(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Transform2D());
MutexLock lock(fd->mutex);
@@ -2060,7 +2110,7 @@ Transform2D TextServerAdvanced::font_get_transform(const RID &p_font_rid) const
}
void TextServerAdvanced::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2071,7 +2121,7 @@ void TextServerAdvanced::font_set_variation_coordinates(const RID &p_font_rid, c
}
Dictionary TextServerAdvanced::font_get_variation_coordinates(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -2079,7 +2129,7 @@ Dictionary TextServerAdvanced::font_get_variation_coordinates(const RID &p_font_
}
void TextServerAdvanced::font_set_oversampling(const RID &p_font_rid, double p_oversampling) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2090,7 +2140,7 @@ void TextServerAdvanced::font_set_oversampling(const RID &p_font_rid, double p_o
}
double TextServerAdvanced::font_get_oversampling(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2098,30 +2148,30 @@ double TextServerAdvanced::font_get_oversampling(const RID &p_font_rid) const {
}
Array TextServerAdvanced::font_get_size_cache_list(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
Array ret;
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) {
+ for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) {
ret.push_back(E.key);
}
return ret;
}
void TextServerAdvanced::font_clear_size_cache(const RID &p_font_rid) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) {
+ for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) {
memdelete(E.value);
}
fd->cache.clear();
}
void TextServerAdvanced::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2132,7 +2182,7 @@ void TextServerAdvanced::font_remove_size_cache(const RID &p_font_rid, const Vec
}
void TextServerAdvanced::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2143,7 +2193,7 @@ void TextServerAdvanced::font_set_ascent(const RID &p_font_rid, int64_t p_size,
}
double TextServerAdvanced::font_get_ascent(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2159,7 +2209,7 @@ double TextServerAdvanced::font_get_ascent(const RID &p_font_rid, int64_t p_size
}
void TextServerAdvanced::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
Vector2i size = _get_size(fd, p_size);
@@ -2169,7 +2219,7 @@ void TextServerAdvanced::font_set_descent(const RID &p_font_rid, int64_t p_size,
}
double TextServerAdvanced::font_get_descent(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2185,7 +2235,7 @@ double TextServerAdvanced::font_get_descent(const RID &p_font_rid, int64_t p_siz
}
void TextServerAdvanced::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2196,7 +2246,7 @@ void TextServerAdvanced::font_set_underline_position(const RID &p_font_rid, int6
}
double TextServerAdvanced::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2212,7 +2262,7 @@ double TextServerAdvanced::font_get_underline_position(const RID &p_font_rid, in
}
void TextServerAdvanced::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2223,7 +2273,7 @@ void TextServerAdvanced::font_set_underline_thickness(const RID &p_font_rid, int
}
double TextServerAdvanced::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2239,7 +2289,7 @@ double TextServerAdvanced::font_get_underline_thickness(const RID &p_font_rid, i
}
void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2255,7 +2305,7 @@ void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, d
}
double TextServerAdvanced::font_get_scale(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2270,60 +2320,8 @@ double TextServerAdvanced::font_get_scale(const RID &p_font_rid, int64_t p_size)
}
}
-void TextServerAdvanced::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
- ERR_FAIL_COND(!fd);
-
- MutexLock lock(fd->mutex);
- Vector2i size = _get_size(fd, p_size);
-
- ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
- switch (p_spacing) {
- case TextServer::SPACING_GLYPH: {
- fd->cache[size]->spacing_glyph = p_value;
- } break;
- case TextServer::SPACING_SPACE: {
- fd->cache[size]->spacing_space = p_value;
- } break;
- default: {
- ERR_FAIL_MSG("Invalid spacing type: " + String::num_int64(p_spacing));
- } break;
- }
-}
-
-int64_t TextServerAdvanced::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
- ERR_FAIL_COND_V(!fd, 0);
-
- MutexLock lock(fd->mutex);
- Vector2i size = _get_size(fd, p_size);
-
- ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0);
-
- switch (p_spacing) {
- case TextServer::SPACING_GLYPH: {
- if (fd->msdf) {
- return fd->cache[size]->spacing_glyph * (double)p_size / (double)fd->msdf_source_size;
- } else {
- return fd->cache[size]->spacing_glyph;
- }
- } break;
- case TextServer::SPACING_SPACE: {
- if (fd->msdf) {
- return fd->cache[size]->spacing_space * (double)p_size / (double)fd->msdf_source_size;
- } else {
- return fd->cache[size]->spacing_space;
- }
- } break;
- default: {
- ERR_FAIL_V_MSG(0, "Invalid spacing type: " + String::num_int64(p_spacing));
- } break;
- }
- return 0;
-}
-
int64_t TextServerAdvanced::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -2335,7 +2333,7 @@ int64_t TextServerAdvanced::font_get_texture_count(const RID &p_font_rid, const
}
void TextServerAdvanced::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
Vector2i size = _get_size_outline(fd, p_size);
@@ -2345,7 +2343,7 @@ void TextServerAdvanced::font_clear_textures(const RID &p_font_rid, const Vector
}
void TextServerAdvanced::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2357,7 +2355,7 @@ void TextServerAdvanced::font_remove_texture(const RID &p_font_rid, const Vector
}
void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
ERR_FAIL_COND(p_image.is_null());
@@ -2383,14 +2381,12 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec
img->generate_mipmaps();
}
- tex.texture = Ref<ImageTexture>();
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
tex.dirty = false;
}
Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Ref<Image>());
MutexLock lock(fd->mutex);
@@ -2407,7 +2403,7 @@ Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, con
}
void TextServerAdvanced::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2423,7 +2419,7 @@ void TextServerAdvanced::font_set_texture_offsets(const RID &p_font_rid, const V
}
PackedInt32Array TextServerAdvanced::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedInt32Array());
MutexLock lock(fd->mutex);
@@ -2436,7 +2432,7 @@ PackedInt32Array TextServerAdvanced::font_get_texture_offsets(const RID &p_font_
}
Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
@@ -2452,7 +2448,7 @@ Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vecto
}
void TextServerAdvanced::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2463,7 +2459,7 @@ void TextServerAdvanced::font_clear_glyphs(const RID &p_font_rid, const Vector2i
}
void TextServerAdvanced::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2474,7 +2470,7 @@ void TextServerAdvanced::font_remove_glyph(const RID &p_font_rid, const Vector2i
}
double TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) const {
- const FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ const FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -2488,7 +2484,7 @@ double TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) c
}
Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -2516,7 +2512,7 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_
}
void TextServerAdvanced::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2531,7 +2527,7 @@ void TextServerAdvanced::font_set_glyph_advance(const RID &p_font_rid, int64_t p
}
Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -2552,7 +2548,7 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const V
}
void TextServerAdvanced::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2567,7 +2563,7 @@ void TextServerAdvanced::font_set_glyph_offset(const RID &p_font_rid, const Vect
}
Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -2588,7 +2584,7 @@ Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vec
}
void TextServerAdvanced::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2603,7 +2599,7 @@ void TextServerAdvanced::font_set_glyph_size(const RID &p_font_rid, const Vector
}
Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Rect2());
MutexLock lock(fd->mutex);
@@ -2619,7 +2615,7 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve
}
void TextServerAdvanced::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2634,7 +2630,7 @@ void TextServerAdvanced::font_set_glyph_uv_rect(const RID &p_font_rid, const Vec
}
int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, -1);
MutexLock lock(fd->mutex);
@@ -2650,7 +2646,7 @@ int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, co
}
void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2665,7 +2661,7 @@ void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const
}
RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, RID());
MutexLock lock(fd->mutex);
@@ -2690,8 +2686,7 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -2705,7 +2700,7 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const
}
Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Size2());
MutexLock lock(fd->mutex);
@@ -2730,8 +2725,7 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -2745,7 +2739,7 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con
}
Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -2795,7 +2789,7 @@ Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, in
}
Array TextServerAdvanced::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
@@ -2804,14 +2798,14 @@ Array TextServerAdvanced::font_get_kerning_list(const RID &p_font_rid, int64_t p
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Array());
Array ret;
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) {
+ for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) {
ret.push_back(E.key);
}
return ret;
}
void TextServerAdvanced::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2822,7 +2816,7 @@ void TextServerAdvanced::font_clear_kerning_map(const RID &p_font_rid, int64_t p
}
void TextServerAdvanced::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2833,7 +2827,7 @@ void TextServerAdvanced::font_remove_kerning(const RID &p_font_rid, int64_t p_si
}
void TextServerAdvanced::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2844,7 +2838,7 @@ void TextServerAdvanced::font_set_kerning(const RID &p_font_rid, int64_t p_size,
}
Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -2877,7 +2871,7 @@ Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_si
}
int64_t TextServerAdvanced::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + ".");
ERR_FAIL_COND_V_MSG((p_variation_selector >= 0xd800 && p_variation_selector <= 0xdfff) || (p_variation_selector > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_variation_selector, 16) + ".");
@@ -2902,7 +2896,7 @@ int64_t TextServerAdvanced::font_get_glyph_index(const RID &p_font_rid, int64_t
}
bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + ".");
@@ -2910,7 +2904,7 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false);
}
- FontDataForSizeAdvanced *at_size = fd->cache.begin()->value;
+ FontForSizeAdvanced *at_size = fd->cache.begin()->value;
#ifdef MODULE_FREETYPE_ENABLED
if (at_size && at_size->face) {
@@ -2921,14 +2915,14 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co
}
String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String());
}
- FontDataForSizeAdvanced *at_size = fd->cache.begin()->value;
+ FontForSizeAdvanced *at_size = fd->cache.begin()->value;
String chars;
#ifdef MODULE_FREETYPE_ENABLED
@@ -2954,7 +2948,7 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const
}
void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
ERR_FAIL_COND_MSG((p_start >= 0xd800 && p_start <= 0xdfff) || (p_start > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_start, 16) + ".");
ERR_FAIL_COND_MSG((p_end >= 0xd800 && p_end <= 0xdfff) || (p_end > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_end, 16) + ".");
@@ -2987,7 +2981,7 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i
}
void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3016,7 +3010,7 @@ void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i
}
void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3062,8 +3056,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -3095,7 +3088,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
}
void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3141,8 +3134,7 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -3174,7 +3166,7 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
}
bool TextServerAdvanced::font_is_language_supported(const RID &p_font_rid, const String &p_language) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -3186,7 +3178,7 @@ bool TextServerAdvanced::font_is_language_supported(const RID &p_font_rid, const
}
void TextServerAdvanced::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3194,7 +3186,7 @@ void TextServerAdvanced::font_set_language_support_override(const RID &p_font_ri
}
bool TextServerAdvanced::font_get_language_support_override(const RID &p_font_rid, const String &p_language) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -3202,7 +3194,7 @@ bool TextServerAdvanced::font_get_language_support_override(const RID &p_font_ri
}
void TextServerAdvanced::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3210,7 +3202,7 @@ void TextServerAdvanced::font_remove_language_support_override(const RID &p_font
}
PackedStringArray TextServerAdvanced::font_get_language_support_overrides(const RID &p_font_rid) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedStringArray());
MutexLock lock(fd->mutex);
@@ -3222,7 +3214,7 @@ PackedStringArray TextServerAdvanced::font_get_language_support_overrides(const
}
bool TextServerAdvanced::font_is_script_supported(const RID &p_font_rid, const String &p_script) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -3236,7 +3228,7 @@ bool TextServerAdvanced::font_is_script_supported(const RID &p_font_rid, const S
}
void TextServerAdvanced::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3244,7 +3236,7 @@ void TextServerAdvanced::font_set_script_support_override(const RID &p_font_rid,
}
bool TextServerAdvanced::font_get_script_support_override(const RID &p_font_rid, const String &p_script) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -3252,7 +3244,7 @@ bool TextServerAdvanced::font_get_script_support_override(const RID &p_font_rid,
}
void TextServerAdvanced::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3260,7 +3252,7 @@ void TextServerAdvanced::font_remove_script_support_override(const RID &p_font_r
}
PackedStringArray TextServerAdvanced::font_get_script_support_overrides(const RID &p_font_rid) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedStringArray());
MutexLock lock(fd->mutex);
@@ -3272,7 +3264,7 @@ PackedStringArray TextServerAdvanced::font_get_script_support_overrides(const RI
}
void TextServerAdvanced::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -3282,7 +3274,7 @@ void TextServerAdvanced::font_set_opentype_feature_overrides(const RID &p_font_r
}
Dictionary TextServerAdvanced::font_get_opentype_feature_overrides(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -3290,7 +3282,7 @@ Dictionary TextServerAdvanced::font_get_opentype_feature_overrides(const RID &p_
}
Dictionary TextServerAdvanced::font_supported_feature_list(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -3300,7 +3292,7 @@ Dictionary TextServerAdvanced::font_supported_feature_list(const RID &p_font_rid
}
Dictionary TextServerAdvanced::font_supported_variation_list(const RID &p_font_rid) const {
- FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -3580,6 +3572,31 @@ bool TextServerAdvanced::shaped_text_get_preserve_control(const RID &p_shaped) c
return sd->preserve_control;
}
+void TextServerAdvanced::shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) {
+ ERR_FAIL_INDEX((int)p_spacing, 4);
+ ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
+ ERR_FAIL_COND(!sd);
+
+ MutexLock lock(sd->mutex);
+ if (sd->extra_spacing[p_spacing] != p_value) {
+ if (sd->parent != RID()) {
+ full_copy(sd);
+ }
+ sd->extra_spacing[p_spacing] = p_value;
+ invalidate(sd, false);
+ }
+}
+
+int64_t TextServerAdvanced::shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const {
+ ERR_FAIL_INDEX_V((int)p_spacing, 4, 0);
+
+ const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
+ ERR_FAIL_COND_V(!sd, 0);
+
+ MutexLock lock(sd->mutex);
+ return sd->extra_spacing[p_spacing];
+}
+
TextServer::Orientation TextServerAdvanced::shaped_text_get_orientation(const RID &p_shaped) const {
const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, TextServer::ORIENTATION_HORIZONTAL);
@@ -3847,6 +3864,9 @@ RID TextServerAdvanced::shaped_text_substr(const RID &p_shaped, int64_t p_start,
new_sd->direction = sd->direction;
new_sd->custom_punct = sd->custom_punct;
new_sd->para_direction = sd->para_direction;
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ new_sd->extra_spacing[i] = sd->extra_spacing[i];
+ }
if (!_shape_substr(new_sd, sd, p_start, p_length)) {
memdelete(new_sd);
@@ -4257,7 +4277,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
int ellipsis_width = 0;
if (add_ellipsis && whitespace_gl_font_rid.is_valid()) {
- ellipsis_width = 3 * dot_adv.x + font_get_spacing(whitespace_gl_font_rid, last_gl_font_size, SPACING_GLYPH) + (cut_per_word ? whitespace_adv.x : 0);
+ ellipsis_width = 3 * dot_adv.x + sd->extra_spacing[SPACING_GLYPH] + (cut_per_word ? whitespace_adv.x : 0);
}
int ell_min_characters = 6;
@@ -4405,7 +4425,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(const RID &p_shaped) {
i++;
}
int r_end = sd->spans[i].end;
- UBreakIterator *bi = ubrk_open(UBRK_LINE, language.ascii().get_data(), data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err);
+ UBreakIterator *bi = ubrk_open(UBRK_LINE, (language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : language.ascii().get_data(), data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err);
if (U_FAILURE(err)) {
// No data loaded - use fallback.
for (int j = r_start; j < r_end; j++) {
@@ -4851,15 +4871,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}
RID f = p_fonts[p_fb_index];
- FontDataAdvanced *fd = font_owner.get_or_null(f);
+ FontAdvanced *fd = font_owner.get_or_null(f);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
Vector2i fss = _get_size(fd, fs);
hb_font_t *hb_font = _font_get_hb_handle(f, fs);
double scale = font_get_scale(f, fs);
- double sp_sp = font_get_spacing(f, fs, SPACING_SPACE);
- double sp_gl = font_get_spacing(f, fs, SPACING_GLYPH);
+ double sp_sp = p_sd->extra_spacing[SPACING_SPACE];
+ double sp_gl = p_sd->extra_spacing[SPACING_GLYPH];
+ bool last_run = (p_sd->end == p_end);
double ea = _get_extra_advance(f, fs);
bool subpos = (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
ERR_FAIL_COND(hb_font == nullptr);
@@ -4873,7 +4894,10 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}
hb_buffer_set_script(p_sd->hb_buffer, p_script);
- if (!p_sd->spans[p_span].language.is_empty()) {
+ if (p_sd->spans[p_span].language.is_empty()) {
+ hb_language_t lang = hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1);
+ hb_buffer_set_language(p_sd->hb_buffer, lang);
+ } else {
hb_language_t lang = hb_language_from_string(p_sd->spans[p_span].language.ascii().get_data(), -1);
hb_buffer_set_language(p_sd->hb_buffer, lang);
}
@@ -4954,10 +4978,13 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
}
gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale));
}
- if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
- gl.advance += sp_sp;
- } else {
- gl.advance += sp_gl;
+ if (!last_run || i < glyph_count - 1) {
+ // Do not add extra spacing to the last glyph of the string.
+ if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) {
+ gl.advance += sp_sp;
+ } else {
+ gl.advance += sp_gl;
+ }
}
if (p_sd->preserve_control) {
@@ -5288,9 +5315,9 @@ Size2 TextServerAdvanced::shaped_text_get_size(const RID &p_shaped) const {
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
}
if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) {
- return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent).ceil();
+ return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM]).ceil();
} else {
- return Size2(sd->ascent + sd->descent, (sd->text_trimmed ? sd->width_trimmed : sd->width)).ceil();
+ return Size2(sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM], (sd->text_trimmed ? sd->width_trimmed : sd->width)).ceil();
}
}
@@ -5302,7 +5329,7 @@ double TextServerAdvanced::shaped_text_get_ascent(const RID &p_shaped) const {
if (!sd->valid) {
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
}
- return sd->ascent;
+ return sd->ascent + sd->extra_spacing[SPACING_TOP];
}
double TextServerAdvanced::shaped_text_get_descent(const RID &p_shaped) const {
@@ -5313,7 +5340,7 @@ double TextServerAdvanced::shaped_text_get_descent(const RID &p_shaped) const {
if (!sd->valid) {
const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped);
}
- return sd->descent;
+ return sd->descent + sd->extra_spacing[SPACING_BOTTOM];
}
double TextServerAdvanced::shaped_text_get_width(const RID &p_shaped) const {
@@ -5627,16 +5654,18 @@ String TextServerAdvanced::strip_diacritics(const String &p_string) const {
}
String TextServerAdvanced::string_to_upper(const String &p_string, const String &p_language) const {
+ const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
+
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
Vector<char16_t> upper;
UErrorCode err = U_ZERO_ERROR;
- int32_t len = u_strToUpper(nullptr, 0, utf16.get_data(), -1, p_language.ascii().get_data(), &err);
+ int32_t len = u_strToUpper(nullptr, 0, utf16.get_data(), -1, lang.ascii().get_data(), &err);
ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err));
upper.resize(len);
err = U_ZERO_ERROR;
- u_strToUpper(upper.ptrw(), len, utf16.get_data(), -1, p_language.ascii().get_data(), &err);
+ u_strToUpper(upper.ptrw(), len, utf16.get_data(), -1, lang.ascii().get_data(), &err);
ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err));
// Convert back to UTF-32.
@@ -5644,16 +5673,17 @@ String TextServerAdvanced::string_to_upper(const String &p_string, const String
}
String TextServerAdvanced::string_to_lower(const String &p_string, const String &p_language) const {
+ const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
Vector<char16_t> lower;
UErrorCode err = U_ZERO_ERROR;
- int32_t len = u_strToLower(nullptr, 0, utf16.get_data(), -1, p_language.ascii().get_data(), &err);
+ int32_t len = u_strToLower(nullptr, 0, utf16.get_data(), -1, lang.ascii().get_data(), &err);
ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err));
lower.resize(len);
err = U_ZERO_ERROR;
- u_strToLower(lower.ptrw(), len, utf16.get_data(), -1, p_language.ascii().get_data(), &err);
+ u_strToLower(lower.ptrw(), len, utf16.get_data(), -1, lang.ascii().get_data(), &err);
ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err));
// Convert back to UTF-32.
@@ -5661,12 +5691,13 @@ String TextServerAdvanced::string_to_lower(const String &p_string, const String
}
PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_string, const String &p_language) const {
+ const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
// Convert to UTF-16.
Char16String utf16 = p_string.utf16();
HashSet<int> breaks;
UErrorCode err = U_ZERO_ERROR;
- UBreakIterator *bi = ubrk_open(UBRK_LINE, p_language.ascii().get_data(), (const UChar *)utf16.get_data(), utf16.length(), &err);
+ UBreakIterator *bi = ubrk_open(UBRK_LINE, lang.ascii().get_data(), (const UChar *)utf16.get_data(), utf16.length(), &err);
if (U_FAILURE(err)) {
// No data loaded - use fallback.
for (int i = 0; i < p_string.length(); i++) {
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index e7690cb70d..87582e8bac 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -133,12 +133,19 @@ class TextServerAdvanced : public TextServerExtension {
};
Vector<NumSystemData> num_systems;
+
+ struct FeatureInfo {
+ StringName name;
+ Variant::Type vtype = Variant::INT;
+ bool hidden = false;
+ };
+
HashMap<StringName, int32_t> feature_sets;
- HashMap<int32_t, StringName> feature_sets_inv;
+ HashMap<int32_t, FeatureInfo> feature_sets_inv;
void _insert_num_systems_lang();
void _insert_feature_sets();
- _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag);
+ _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype = Variant::INT, bool p_hidden = false);
// ICU support data.
@@ -176,7 +183,7 @@ class TextServerAdvanced : public TextServerExtension {
Vector2 advance;
};
- struct FontDataForSizeAdvanced {
+ struct FontForSizeAdvanced {
double ascent = 0.0;
double descent = 0.0;
double underline_position = 0.0;
@@ -184,9 +191,6 @@ class TextServerAdvanced : public TextServerExtension {
double scale = 1.0;
double oversampling = 1.0;
- int spacing_glyph = 0;
- int spacing_space = 0;
-
Vector2i size;
Vector<FontTexture> textures;
@@ -199,7 +203,7 @@ class TextServerAdvanced : public TextServerExtension {
FT_StreamRec stream;
#endif
- ~FontDataForSizeAdvanced() {
+ ~FontForSizeAdvanced() {
if (hb_handle != nullptr) {
hb_font_destroy(hb_handle);
}
@@ -211,7 +215,7 @@ class TextServerAdvanced : public TextServerExtension {
}
};
- struct FontDataAdvanced {
+ struct FontAdvanced {
Mutex mutex;
bool antialiased = true;
@@ -232,7 +236,7 @@ class TextServerAdvanced : public TextServerExtension {
String font_name;
String style_name;
- HashMap<Vector2i, FontDataForSizeAdvanced *, VariantHasher, VariantComparator> cache;
+ HashMap<Vector2i, FontForSizeAdvanced *, VariantHasher, VariantComparator> cache;
bool face_init = false;
HashSet<uint32_t> supported_scripts;
@@ -250,28 +254,28 @@ class TextServerAdvanced : public TextServerExtension {
int face_index = 0;
mutable ThreadWorkPool work_pool;
- ~FontDataAdvanced() {
+ ~FontAdvanced() {
work_pool.finish();
- for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : cache) {
+ for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : cache) {
memdelete(E.value);
}
cache.clear();
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
- _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
+ _FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
#ifdef MODULE_FREETYPE_ENABLED
- _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
+ _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
#endif
- _FORCE_INLINE_ bool _ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
- _FORCE_INLINE_ bool _ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const;
- _FORCE_INLINE_ void _font_clear_cache(FontDataAdvanced *p_font_data);
+ _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
+ _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const;
+ _FORCE_INLINE_ void _font_clear_cache(FontAdvanced *p_font_data);
void _generateMTSDF_threaded(uint32_t y, void *p_td) const;
- _FORCE_INLINE_ Vector2i _get_size(const FontDataAdvanced *p_font_data, int p_size) const {
+ _FORCE_INLINE_ Vector2i _get_size(const FontAdvanced *p_font_data, int p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@@ -281,7 +285,7 @@ class TextServerAdvanced : public TextServerExtension {
}
}
- _FORCE_INLINE_ Vector2i _get_size_outline(const FontDataAdvanced *p_font_data, const Vector2i &p_size) const {
+ _FORCE_INLINE_ Vector2i _get_size_outline(const FontAdvanced *p_font_data, const Vector2i &p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@@ -292,6 +296,8 @@ class TextServerAdvanced : public TextServerExtension {
}
_FORCE_INLINE_ double _get_extra_advance(RID p_font_rid, int p_font_size) const;
+ _FORCE_INLINE_ Variant::Type _get_tag_type(int64_t p_tag) const;
+ _FORCE_INLINE_ bool _get_tag_hidden(int64_t p_tag) const;
// Shaped text cache data.
struct TrimData {
@@ -351,6 +357,7 @@ class TextServerAdvanced : public TextServerExtension {
double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical.
double width = 0.0; // Width for horizontal layout, height for vertical.
double width_trimmed = 0.0;
+ int extra_spacing[4] = { 0, 0, 0, 0 };
double upos = 0.0;
double uthk = 0.0;
@@ -389,7 +396,7 @@ class TextServerAdvanced : public TextServerExtension {
// Common data.
double oversampling = 1.0;
- mutable RID_PtrOwner<FontDataAdvanced> font_owner;
+ mutable RID_PtrOwner<FontAdvanced> font_owner;
mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner;
void _realign(ShapedTextDataAdvanced *p_sd) const;
@@ -407,11 +414,11 @@ class TextServerAdvanced : public TextServerExtension {
static hb_font_funcs_t *funcs;
struct bmp_font_t {
- TextServerAdvanced::FontDataForSizeAdvanced *face = nullptr;
+ TextServerAdvanced::FontForSizeAdvanced *face = nullptr;
bool unref = false; /* Whether to destroy bm_face when done. */
};
- static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref);
+ static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref);
static void _bmp_font_destroy(void *p_data);
static hb_bool_t _bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data);
static hb_position_t _bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data);
@@ -422,8 +429,8 @@ class TextServerAdvanced : public TextServerExtension {
static hb_bool_t _bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data);
static void _bmp_create_font_funcs();
static void _bmp_free_font_funcs();
- static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref);
- static hb_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy);
+ static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref);
+ static hb_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy);
hb_font_t *_font_get_hb_handle(const RID &p_font, int64_t p_font_size) const;
@@ -546,9 +553,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
-
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
@@ -646,6 +650,9 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
+
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index f93c5909c9..7ccc9e3533 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -104,7 +104,7 @@ int64_t TextServerFallback::get_features() const {
void TextServerFallback::free_rid(const RID &p_rid) {
_THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) {
- FontDataFallback *fd = font_owner.get_or_null(p_rid);
+ FontFallback *fd = font_owner.get_or_null(p_rid);
font_owner.free(p_rid);
memdelete(fd);
} else if (shaped_owner.owns(p_rid)) {
@@ -199,7 +199,7 @@ String TextServerFallback::tag_to_name(int64_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
+_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -397,7 +397,7 @@ void TextServerFallback::_generateMTSDF_threaded(uint32_t y, void *p_td) const {
}
}
-_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const {
+_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const {
msdfgen::Shape shape;
shape.contours.clear();
@@ -502,7 +502,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
#endif
#ifdef MODULE_FREETYPE_ENABLED
-_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontDataForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const {
+_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const {
int w = bitmap.width;
int h = bitmap.rows;
@@ -579,12 +579,12 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
/* Font Cache */
/*************************************************************************/
-_FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
+_FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false);
int32_t glyph_index = p_glyph & 0xffffff; // Remove subpixel shifts.
- FontDataForSizeFallback *fd = p_font_data->cache[p_size];
+ FontForSizeFallback *fd = p_font_data->cache[p_size];
if (fd->glyph_map.has(p_glyph)) {
return fd->glyph_map[p_glyph].found;
}
@@ -705,13 +705,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
return false;
}
-_FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const {
+_FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *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;
}
- FontDataForSizeFallback *fd = memnew(FontDataForSizeFallback);
+ FontForSizeFallback *fd = memnew(FontForSizeFallback);
fd->size = p_size;
if (p_font_data->data_ptr && (p_font_data->data_size > 0)) {
// Init dynamic font.
@@ -851,8 +851,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback
return true;
}
-_FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontDataFallback *p_font_data) {
- for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : p_font_data->cache) {
+_FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) {
+ for (const KeyValue<Vector2i, FontForSizeFallback *> &E : p_font_data->cache) {
memdelete(E.value);
}
@@ -864,13 +864,13 @@ _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontDataFallback *p_fo
RID TextServerFallback::create_font() {
_THREAD_SAFE_METHOD_
- FontDataFallback *fd = memnew(FontDataFallback);
+ FontFallback *fd = memnew(FontFallback);
return font_owner.make_rid(fd);
}
void TextServerFallback::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -881,7 +881,7 @@ void TextServerFallback::font_set_data(const RID &p_font_rid, const PackedByteAr
}
void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -892,7 +892,7 @@ void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t
}
void TextServerFallback::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -905,7 +905,7 @@ void TextServerFallback::font_set_face_index(const RID &p_font_rid, int64_t p_fa
ERR_FAIL_COND(p_face_index < 0);
ERR_FAIL_COND(p_face_index >= 0x7FFF);
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -916,7 +916,7 @@ void TextServerFallback::font_set_face_index(const RID &p_font_rid, int64_t p_fa
}
int64_t TextServerFallback::font_get_face_index(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -924,7 +924,7 @@ int64_t TextServerFallback::font_get_face_index(const RID &p_font_rid) const {
}
int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -965,7 +965,7 @@ int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const {
}
int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -975,7 +975,7 @@ int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid)
}
void TextServerFallback::font_set_style_name(const RID &p_font_rid, const String &p_name) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -985,7 +985,7 @@ void TextServerFallback::font_set_style_name(const RID &p_font_rid, const String
}
String TextServerFallback::font_get_style_name(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
@@ -995,7 +995,7 @@ String TextServerFallback::font_get_style_name(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_name(const RID &p_font_rid, const String &p_name) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1005,7 +1005,7 @@ void TextServerFallback::font_set_name(const RID &p_font_rid, const String &p_na
}
String TextServerFallback::font_get_name(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
@@ -1015,7 +1015,7 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1026,7 +1026,7 @@ void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_anti
}
bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1034,12 +1034,12 @@ bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
if (fd->mipmaps != p_generate_mipmaps) {
- for (KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) {
+ for (KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) {
for (int i = 0; i < E.value->textures.size(); i++) {
E.value->textures.write[i].dirty = true;
}
@@ -1049,7 +1049,7 @@ void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p
}
bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1057,7 +1057,7 @@ bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const
}
void TextServerFallback::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1068,7 +1068,7 @@ void TextServerFallback::font_set_multichannel_signed_distance_field(const RID &
}
bool TextServerFallback::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1076,7 +1076,7 @@ bool TextServerFallback::font_is_multichannel_signed_distance_field(const RID &p
}
void TextServerFallback::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1087,7 +1087,7 @@ void TextServerFallback::font_set_msdf_pixel_range(const RID &p_font_rid, int64_
}
int64_t TextServerFallback::font_get_msdf_pixel_range(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1095,7 +1095,7 @@ int64_t TextServerFallback::font_get_msdf_pixel_range(const RID &p_font_rid) con
}
void TextServerFallback::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1106,7 +1106,7 @@ void TextServerFallback::font_set_msdf_size(const RID &p_font_rid, int64_t p_msd
}
int64_t TextServerFallback::font_get_msdf_size(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1114,7 +1114,7 @@ int64_t TextServerFallback::font_get_msdf_size(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1122,7 +1122,7 @@ void TextServerFallback::font_set_fixed_size(const RID &p_font_rid, int64_t p_fi
}
int64_t TextServerFallback::font_get_fixed_size(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1130,7 +1130,7 @@ int64_t TextServerFallback::font_get_fixed_size(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1141,7 +1141,7 @@ void TextServerFallback::font_set_force_autohinter(const RID &p_font_rid, bool p
}
bool TextServerFallback::font_is_force_autohinter(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -1149,7 +1149,7 @@ bool TextServerFallback::font_is_force_autohinter(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1160,7 +1160,7 @@ void TextServerFallback::font_set_hinting(const RID &p_font_rid, TextServer::Hin
}
TextServer::Hinting TextServerFallback::font_get_hinting(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, HINTING_NONE);
MutexLock lock(fd->mutex);
@@ -1168,7 +1168,7 @@ TextServer::Hinting TextServerFallback::font_get_hinting(const RID &p_font_rid)
}
void TextServerFallback::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1176,7 +1176,7 @@ void TextServerFallback::font_set_subpixel_positioning(const RID &p_font_rid, Te
}
TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positioning(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED);
MutexLock lock(fd->mutex);
@@ -1184,7 +1184,7 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin
}
void TextServerFallback::font_set_embolden(const RID &p_font_rid, double p_strength) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1195,7 +1195,7 @@ void TextServerFallback::font_set_embolden(const RID &p_font_rid, double p_stren
}
double TextServerFallback::font_get_embolden(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1203,7 +1203,7 @@ double TextServerFallback::font_get_embolden(const RID &p_font_rid) const {
}
void TextServerFallback::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1214,7 +1214,7 @@ void TextServerFallback::font_set_transform(const RID &p_font_rid, const Transfo
}
Transform2D TextServerFallback::font_get_transform(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Transform2D());
MutexLock lock(fd->mutex);
@@ -1222,7 +1222,7 @@ Transform2D TextServerFallback::font_get_transform(const RID &p_font_rid) const
}
void TextServerFallback::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1233,7 +1233,7 @@ void TextServerFallback::font_set_variation_coordinates(const RID &p_font_rid, c
}
Dictionary TextServerFallback::font_get_variation_coordinates(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -1241,7 +1241,7 @@ Dictionary TextServerFallback::font_get_variation_coordinates(const RID &p_font_
}
void TextServerFallback::font_set_oversampling(const RID &p_font_rid, double p_oversampling) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1252,7 +1252,7 @@ void TextServerFallback::font_set_oversampling(const RID &p_font_rid, double p_o
}
double TextServerFallback::font_get_oversampling(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1260,30 +1260,30 @@ double TextServerFallback::font_get_oversampling(const RID &p_font_rid) const {
}
Array TextServerFallback::font_get_size_cache_list(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
Array ret;
- for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) {
+ for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) {
ret.push_back(E.key);
}
return ret;
}
void TextServerFallback::font_clear_size_cache(const RID &p_font_rid) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
- for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) {
+ for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) {
memdelete(E.value);
}
fd->cache.clear();
}
void TextServerFallback::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1294,7 +1294,7 @@ void TextServerFallback::font_remove_size_cache(const RID &p_font_rid, const Vec
}
void TextServerFallback::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1305,7 +1305,7 @@ void TextServerFallback::font_set_ascent(const RID &p_font_rid, int64_t p_size,
}
double TextServerFallback::font_get_ascent(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1321,7 +1321,7 @@ double TextServerFallback::font_get_ascent(const RID &p_font_rid, int64_t p_size
}
void TextServerFallback::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
Vector2i size = _get_size(fd, p_size);
@@ -1331,7 +1331,7 @@ void TextServerFallback::font_set_descent(const RID &p_font_rid, int64_t p_size,
}
double TextServerFallback::font_get_descent(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1347,7 +1347,7 @@ double TextServerFallback::font_get_descent(const RID &p_font_rid, int64_t p_siz
}
void TextServerFallback::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1358,7 +1358,7 @@ void TextServerFallback::font_set_underline_position(const RID &p_font_rid, int6
}
double TextServerFallback::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1374,7 +1374,7 @@ double TextServerFallback::font_get_underline_position(const RID &p_font_rid, in
}
void TextServerFallback::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1385,7 +1385,7 @@ void TextServerFallback::font_set_underline_thickness(const RID &p_font_rid, int
}
double TextServerFallback::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1401,7 +1401,7 @@ double TextServerFallback::font_get_underline_thickness(const RID &p_font_rid, i
}
void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1417,7 +1417,7 @@ void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, d
}
double TextServerFallback::font_get_scale(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0.0);
MutexLock lock(fd->mutex);
@@ -1432,60 +1432,8 @@ double TextServerFallback::font_get_scale(const RID &p_font_rid, int64_t p_size)
}
}
-void TextServerFallback::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
- ERR_FAIL_COND(!fd);
-
- MutexLock lock(fd->mutex);
- Vector2i size = _get_size(fd, p_size);
-
- ERR_FAIL_COND(!_ensure_cache_for_size(fd, size));
- switch (p_spacing) {
- case TextServer::SPACING_GLYPH: {
- fd->cache[size]->spacing_glyph = p_value;
- } break;
- case TextServer::SPACING_SPACE: {
- fd->cache[size]->spacing_space = p_value;
- } break;
- default: {
- ERR_FAIL_MSG("Invalid spacing type: " + String::num_int64(p_spacing));
- } break;
- }
-}
-
-int64_t TextServerFallback::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
- ERR_FAIL_COND_V(!fd, 0);
-
- MutexLock lock(fd->mutex);
- Vector2i size = _get_size(fd, p_size);
-
- ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0);
-
- switch (p_spacing) {
- case TextServer::SPACING_GLYPH: {
- if (fd->msdf) {
- return fd->cache[size]->spacing_glyph * (double)p_size / (double)fd->msdf_source_size;
- } else {
- return fd->cache[size]->spacing_glyph;
- }
- } break;
- case TextServer::SPACING_SPACE: {
- if (fd->msdf) {
- return fd->cache[size]->spacing_space * (double)p_size / (double)fd->msdf_source_size;
- } else {
- return fd->cache[size]->spacing_space;
- }
- } break;
- default: {
- ERR_FAIL_V_MSG(0, "Invalid spacing type: " + String::num_int64(p_spacing));
- } break;
- }
- return 0;
-}
-
int64_t TextServerFallback::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, 0);
MutexLock lock(fd->mutex);
@@ -1497,7 +1445,7 @@ int64_t TextServerFallback::font_get_texture_count(const RID &p_font_rid, const
}
void TextServerFallback::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
Vector2i size = _get_size_outline(fd, p_size);
@@ -1507,7 +1455,7 @@ void TextServerFallback::font_clear_textures(const RID &p_font_rid, const Vector
}
void TextServerFallback::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1519,7 +1467,7 @@ void TextServerFallback::font_remove_texture(const RID &p_font_rid, const Vector
}
void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
ERR_FAIL_COND(p_image.is_null());
@@ -1545,14 +1493,12 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec
img->generate_mipmaps();
}
- tex.texture = Ref<ImageTexture>();
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
tex.dirty = false;
}
Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Ref<Image>());
MutexLock lock(fd->mutex);
@@ -1569,7 +1515,7 @@ Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, con
}
void TextServerFallback::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1585,7 +1531,7 @@ void TextServerFallback::font_set_texture_offsets(const RID &p_font_rid, const V
}
PackedInt32Array TextServerFallback::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedInt32Array());
MutexLock lock(fd->mutex);
@@ -1598,7 +1544,7 @@ PackedInt32Array TextServerFallback::font_get_texture_offsets(const RID &p_font_
}
Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
@@ -1614,7 +1560,7 @@ Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vecto
}
void TextServerFallback::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1625,7 +1571,7 @@ void TextServerFallback::font_clear_glyphs(const RID &p_font_rid, const Vector2i
}
void TextServerFallback::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1636,7 +1582,7 @@ void TextServerFallback::font_remove_glyph(const RID &p_font_rid, const Vector2i
}
Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -1664,7 +1610,7 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_
}
void TextServerFallback::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1679,7 +1625,7 @@ void TextServerFallback::font_set_glyph_advance(const RID &p_font_rid, int64_t p
}
Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -1700,7 +1646,7 @@ Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const V
}
void TextServerFallback::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1715,7 +1661,7 @@ void TextServerFallback::font_set_glyph_offset(const RID &p_font_rid, const Vect
}
Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -1736,7 +1682,7 @@ Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vec
}
void TextServerFallback::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1751,7 +1697,7 @@ void TextServerFallback::font_set_glyph_size(const RID &p_font_rid, const Vector
}
Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Rect2());
MutexLock lock(fd->mutex);
@@ -1767,7 +1713,7 @@ Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve
}
void TextServerFallback::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1782,7 +1728,7 @@ void TextServerFallback::font_set_glyph_uv_rect(const RID &p_font_rid, const Vec
}
int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, -1);
MutexLock lock(fd->mutex);
@@ -1798,7 +1744,7 @@ int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, co
}
void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1813,7 +1759,7 @@ void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const
}
RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, RID());
MutexLock lock(fd->mutex);
@@ -1838,8 +1784,7 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -1853,7 +1798,7 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const
}
Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Size2());
MutexLock lock(fd->mutex);
@@ -1878,8 +1823,7 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -1893,7 +1837,7 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con
}
Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -1943,7 +1887,7 @@ Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, in
}
Array TextServerFallback::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Array());
MutexLock lock(fd->mutex);
@@ -1959,7 +1903,7 @@ Array TextServerFallback::font_get_kerning_list(const RID &p_font_rid, int64_t p
}
void TextServerFallback::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1970,7 +1914,7 @@ void TextServerFallback::font_clear_kerning_map(const RID &p_font_rid, int64_t p
}
void TextServerFallback::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1981,7 +1925,7 @@ void TextServerFallback::font_remove_kerning(const RID &p_font_rid, int64_t p_si
}
void TextServerFallback::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -1992,7 +1936,7 @@ void TextServerFallback::font_set_kerning(const RID &p_font_rid, int64_t p_size,
}
Vector2 TextServerFallback::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
MutexLock lock(fd->mutex);
@@ -2032,7 +1976,7 @@ int64_t TextServerFallback::font_get_glyph_index(const RID &p_font_rid, int64_t
}
bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + ".");
@@ -2040,7 +1984,7 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false);
}
- FontDataForSizeFallback *at_size = fd->cache.begin()->value;
+ FontForSizeFallback *at_size = fd->cache.begin()->value;
#ifdef MODULE_FREETYPE_ENABLED
if (at_size && at_size->face) {
@@ -2051,14 +1995,14 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co
}
String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, String());
MutexLock lock(fd->mutex);
if (fd->cache.is_empty()) {
ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String());
}
- FontDataForSizeFallback *at_size = fd->cache.begin()->value;
+ FontForSizeFallback *at_size = fd->cache.begin()->value;
String chars;
#ifdef MODULE_FREETYPE_ENABLED
@@ -2084,7 +2028,7 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const
}
void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
ERR_FAIL_COND_MSG((p_start >= 0xd800 && p_start <= 0xdfff) || (p_start > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_start, 16) + ".");
ERR_FAIL_COND_MSG((p_end >= 0xd800 && p_end <= 0xdfff) || (p_end > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_end, 16) + ".");
@@ -2117,7 +2061,7 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i
}
void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2146,7 +2090,7 @@ void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i
}
void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2192,8 +2136,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -2225,7 +2168,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
}
void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2271,8 +2214,7 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
img->generate_mipmaps();
}
if (tex.texture.is_null()) {
- tex.texture.instantiate();
- tex.texture->create_from_image(img);
+ tex.texture = ImageTexture::create_from_image(img);
} else {
tex.texture->update(img);
}
@@ -2304,7 +2246,7 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
}
bool TextServerFallback::font_is_language_supported(const RID &p_font_rid, const String &p_language) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -2316,7 +2258,7 @@ bool TextServerFallback::font_is_language_supported(const RID &p_font_rid, const
}
void TextServerFallback::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2324,7 +2266,7 @@ void TextServerFallback::font_set_language_support_override(const RID &p_font_ri
}
bool TextServerFallback::font_get_language_support_override(const RID &p_font_rid, const String &p_language) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -2332,7 +2274,7 @@ bool TextServerFallback::font_get_language_support_override(const RID &p_font_ri
}
void TextServerFallback::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2340,7 +2282,7 @@ void TextServerFallback::font_remove_language_support_override(const RID &p_font
}
PackedStringArray TextServerFallback::font_get_language_support_overrides(const RID &p_font_rid) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedStringArray());
MutexLock lock(fd->mutex);
@@ -2352,7 +2294,7 @@ PackedStringArray TextServerFallback::font_get_language_support_overrides(const
}
bool TextServerFallback::font_is_script_supported(const RID &p_font_rid, const String &p_script) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -2364,7 +2306,7 @@ bool TextServerFallback::font_is_script_supported(const RID &p_font_rid, const S
}
void TextServerFallback::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2372,7 +2314,7 @@ void TextServerFallback::font_set_script_support_override(const RID &p_font_rid,
}
bool TextServerFallback::font_get_script_support_override(const RID &p_font_rid, const String &p_script) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, false);
MutexLock lock(fd->mutex);
@@ -2380,7 +2322,7 @@ bool TextServerFallback::font_get_script_support_override(const RID &p_font_rid,
}
void TextServerFallback::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2390,7 +2332,7 @@ void TextServerFallback::font_remove_script_support_override(const RID &p_font_r
}
PackedStringArray TextServerFallback::font_get_script_support_overrides(const RID &p_font_rid) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, PackedStringArray());
MutexLock lock(fd->mutex);
@@ -2402,7 +2344,7 @@ PackedStringArray TextServerFallback::font_get_script_support_overrides(const RI
}
void TextServerFallback::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex);
@@ -2412,7 +2354,7 @@ void TextServerFallback::font_set_opentype_feature_overrides(const RID &p_font_r
}
Dictionary TextServerFallback::font_get_opentype_feature_overrides(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -2424,7 +2366,7 @@ Dictionary TextServerFallback::font_supported_feature_list(const RID &p_font_rid
}
Dictionary TextServerFallback::font_supported_variation_list(const RID &p_font_rid) const {
- FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ FontFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
MutexLock lock(fd->mutex);
@@ -2630,6 +2572,31 @@ bool TextServerFallback::shaped_text_get_preserve_control(const RID &p_shaped) c
return sd->preserve_control;
}
+void TextServerFallback::shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) {
+ ERR_FAIL_INDEX((int)p_spacing, 4);
+ ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
+ ERR_FAIL_COND(!sd);
+
+ MutexLock lock(sd->mutex);
+ if (sd->extra_spacing[p_spacing] != p_value) {
+ if (sd->parent != RID()) {
+ full_copy(sd);
+ }
+ sd->extra_spacing[p_spacing] = p_value;
+ invalidate(sd);
+ }
+}
+
+int64_t TextServerFallback::shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const {
+ ERR_FAIL_INDEX_V((int)p_spacing, 4, 0);
+
+ const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
+ ERR_FAIL_COND_V(!sd, 0);
+
+ MutexLock lock(sd->mutex);
+ return sd->extra_spacing[p_spacing];
+}
+
int64_t TextServerFallback::shaped_get_span_count(const RID &p_shaped) const {
ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped);
ERR_FAIL_COND_V(!sd, 0);
@@ -2912,6 +2879,9 @@ RID TextServerFallback::shaped_text_substr(const RID &p_shaped, int64_t p_start,
new_sd->sort_valid = false;
new_sd->upos = sd->upos;
new_sd->uthk = sd->uthk;
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ new_sd->extra_spacing[i] = sd->extra_spacing[i];
+ }
if (p_length > 0) {
new_sd->text = sd->text.substr(p_start - sd->start, p_length);
@@ -3289,7 +3259,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
int ellipsis_width = 0;
if (add_ellipsis && whitespace_gl_font_rid.is_valid()) {
- ellipsis_width = 3 * dot_adv.x + font_get_spacing(whitespace_gl_font_rid, last_gl_font_size, SPACING_GLYPH) + (cut_per_word ? whitespace_adv.x : 0);
+ ellipsis_width = 3 * dot_adv.x + sd->extra_spacing[SPACING_GLYPH] + (cut_per_word ? whitespace_adv.x : 0);
}
int ell_min_characters = 6;
@@ -3491,10 +3461,13 @@ bool TextServerFallback::shaped_text_shape(const RID &p_shaped) {
sd->descent = MAX(sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5));
}
}
- if (font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE) && is_whitespace(sd->text[j - sd->start])) {
- gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE);
- } else {
- gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_GLYPH);
+ if (j < sd->end - 1) {
+ // Do not add extra spacing to the last glyph of the string.
+ if (is_whitespace(sd->text[j - sd->start])) {
+ gl.advance += sd->extra_spacing[SPACING_SPACE];
+ } else {
+ gl.advance += sd->extra_spacing[SPACING_GLYPH];
+ }
}
sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size));
sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size));
@@ -3621,9 +3594,9 @@ Size2 TextServerFallback::shaped_text_get_size(const RID &p_shaped) const {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) {
- return Size2(sd->width, sd->ascent + sd->descent).ceil();
+ return Size2(sd->width, sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM]).ceil();
} else {
- return Size2(sd->ascent + sd->descent, sd->width).ceil();
+ return Size2(sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM], sd->width).ceil();
}
}
@@ -3635,7 +3608,7 @@ double TextServerFallback::shaped_text_get_ascent(const RID &p_shaped) const {
if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
- return sd->ascent;
+ return sd->ascent + sd->extra_spacing[SPACING_TOP];
}
double TextServerFallback::shaped_text_get_descent(const RID &p_shaped) const {
@@ -3646,7 +3619,7 @@ double TextServerFallback::shaped_text_get_descent(const RID &p_shaped) const {
if (!sd->valid) {
const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped);
}
- return sd->descent;
+ return sd->descent + sd->extra_spacing[SPACING_BOTTOM];
}
double TextServerFallback::shaped_text_get_width(const RID &p_shaped) const {
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index e4c81aed5b..8b10c9e99e 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -144,7 +144,7 @@ class TextServerFallback : public TextServerExtension {
Vector2 advance;
};
- struct FontDataForSizeFallback {
+ struct FontForSizeFallback {
double ascent = 0.0;
double descent = 0.0;
double underline_position = 0.0;
@@ -152,9 +152,6 @@ class TextServerFallback : public TextServerExtension {
double scale = 1.0;
double oversampling = 1.0;
- int spacing_glyph = 0;
- int spacing_space = 0;
-
Vector2i size;
Vector<FontTexture> textures;
@@ -166,7 +163,7 @@ class TextServerFallback : public TextServerExtension {
FT_StreamRec stream;
#endif
- ~FontDataForSizeFallback() {
+ ~FontForSizeFallback() {
#ifdef MODULE_FREETYPE_ENABLED
if (face != nullptr) {
FT_Done_Face(face);
@@ -175,7 +172,7 @@ class TextServerFallback : public TextServerExtension {
}
};
- struct FontDataFallback {
+ struct FontFallback {
Mutex mutex;
bool antialiased = true;
@@ -196,7 +193,7 @@ class TextServerFallback : public TextServerExtension {
String font_name;
String style_name;
- HashMap<Vector2i, FontDataForSizeFallback *, VariantHasher, VariantComparator> cache;
+ HashMap<Vector2i, FontForSizeFallback *, VariantHasher, VariantComparator> cache;
bool face_init = false;
Dictionary supported_varaitions;
@@ -213,28 +210,28 @@ class TextServerFallback : public TextServerExtension {
mutable ThreadWorkPool work_pool;
- ~FontDataFallback() {
+ ~FontFallback() {
work_pool.finish();
- for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : cache) {
+ for (const KeyValue<Vector2i, FontForSizeFallback *> &E : cache) {
memdelete(E.value);
}
cache.clear();
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
- _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
+ _FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
#ifdef MODULE_FREETYPE_ENABLED
- _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
+ _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const;
#endif
- _FORCE_INLINE_ bool _ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
- _FORCE_INLINE_ bool _ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const;
- _FORCE_INLINE_ void _font_clear_cache(FontDataFallback *p_font_data);
+ _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const;
+ _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const;
+ _FORCE_INLINE_ void _font_clear_cache(FontFallback *p_font_data);
void _generateMTSDF_threaded(uint32_t y, void *p_td) const;
- _FORCE_INLINE_ Vector2i _get_size(const FontDataFallback *p_font_data, int p_size) const {
+ _FORCE_INLINE_ Vector2i _get_size(const FontFallback *p_font_data, int p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@@ -244,7 +241,7 @@ class TextServerFallback : public TextServerExtension {
}
}
- _FORCE_INLINE_ Vector2i _get_size_outline(const FontDataFallback *p_font_data, const Vector2i &p_size) const {
+ _FORCE_INLINE_ Vector2i _get_size_outline(const FontFallback *p_font_data, const Vector2i &p_size) const {
if (p_font_data->msdf) {
return Vector2i(p_font_data->msdf_source_size, 0);
} else if (p_font_data->fixed_size > 0) {
@@ -312,6 +309,7 @@ class TextServerFallback : public TextServerExtension {
double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical.
double width = 0.0; // Width for horizontal layout, height for vertical.
double width_trimmed = 0.0;
+ int extra_spacing[4] = { 0, 0, 0, 0 };
double upos = 0.0;
double uthk = 0.0;
@@ -326,7 +324,7 @@ class TextServerFallback : public TextServerExtension {
// Common data.
double oversampling = 1.0;
- mutable RID_PtrOwner<FontDataFallback> font_owner;
+ mutable RID_PtrOwner<FontFallback> font_owner;
mutable RID_PtrOwner<ShapedTextDataFallback> shaped_owner;
void _realign(ShapedTextDataFallback *p_sd) const;
@@ -437,9 +435,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
-
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
@@ -536,6 +531,9 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
+
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 77e370849f..c4462ba687 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -331,7 +331,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
Ref<Image> img;
img.instantiate();
img->create(w, h, false, Image::FORMAT_RGBA8);
- texture->create_from_image(img);
+ texture->set_image(img);
} else {
/* tear down the partial theora setup */
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index c5bcf23c8e..742fa75bb7 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -2435,6 +2435,9 @@ void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) c
void VisualScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const {
}
+void VisualScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const {
+}
+
void VisualScriptLanguage::profiling_start() {
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index c2e4d0e597..716310f59b 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -599,6 +599,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual void get_public_functions(List<MethodInfo> *p_functions) const override;
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override;
+ virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override;
virtual void profiling_start() override;
virtual void profiling_stop() override;
diff --git a/modules/webrtc/webrtc_peer_connection_js.cpp b/modules/webrtc/webrtc_peer_connection_js.cpp
index 90e19fe4f1..ee3a302fa2 100644
--- a/modules/webrtc/webrtc_peer_connection_js.cpp
+++ b/modules/webrtc/webrtc_peer_connection_js.cpp
@@ -57,7 +57,7 @@ void WebRTCPeerConnectionJS::_on_error(void *p_obj) {
void WebRTCPeerConnectionJS::_on_data_channel(void *p_obj, int p_id) {
WebRTCPeerConnectionJS *peer = static_cast<WebRTCPeerConnectionJS *>(p_obj);
- peer->emit_signal(SNAME("data_channel_received"), Ref<WebRTCDataChannelJS>(new WebRTCDataChannelJS(p_id)));
+ peer->emit_signal(SNAME("data_channel_received"), Ref<WebRTCDataChannel>(memnew(WebRTCDataChannelJS(p_id))));
}
void WebRTCPeerConnectionJS::close() {
diff --git a/modules/webrtc/webrtc_peer_connection_js.h b/modules/webrtc/webrtc_peer_connection_js.h
index 8fa5ea7779..76b8c7fff8 100644
--- a/modules/webrtc/webrtc_peer_connection_js.h
+++ b/modules/webrtc/webrtc_peer_connection_js.h
@@ -52,6 +52,8 @@ extern int godot_js_rtc_pc_datachannel_create(int p_id, const char *p_label, con
}
class WebRTCPeerConnectionJS : public WebRTCPeerConnection {
+ GDCLASS(WebRTCPeerConnectionJS, WebRTCPeerConnection);
+
private:
int _js_id;
ConnectionState _conn_state;
diff --git a/platform/android/SCsub b/platform/android/SCsub
index ad226255bc..d370a4d18d 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -6,6 +6,7 @@ android_files = [
"os_android.cpp",
"android_input_handler.cpp",
"file_access_android.cpp",
+ "file_access_filesystem_jandroid.cpp",
"audio_driver_opensl.cpp",
"dir_access_jandroid.cpp",
"tts_android.cpp",
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 47cfade765..2ff5bf59ea 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -96,22 +96,19 @@ def configure(env):
if env["android_arch"] == "armv7":
target_triple = "armv7a-linux-androideabi"
- bin_utils = "arm-linux-androideabi"
env.extra_suffix = ".armv7" + env.extra_suffix
elif env["android_arch"] == "arm64v8":
target_triple = "aarch64-linux-android"
- bin_utils = target_triple
env.extra_suffix = ".armv8" + env.extra_suffix
elif env["android_arch"] == "x86":
target_triple = "i686-linux-android"
- bin_utils = target_triple
env.extra_suffix = ".x86" + env.extra_suffix
elif env["android_arch"] == "x86_64":
target_triple = "x86_64-linux-android"
- bin_utils = target_triple
env.extra_suffix = ".x86_64" + env.extra_suffix
target_option = ["-target", target_triple + str(get_min_sdk_version(env["ndk_platform"]))]
+ env.Append(ASFLAGS=[target_option, "-c"])
env.Append(CCFLAGS=target_option)
env.Append(LINKFLAGS=target_option)
@@ -152,13 +149,12 @@ def configure(env):
toolchain_path = ndk_root + "/toolchains/llvm/prebuilt/" + host_subpath
compiler_path = toolchain_path + "/bin"
- bin_utils_path = toolchain_path + "/" + bin_utils + "/bin"
env["CC"] = compiler_path + "/clang"
env["CXX"] = compiler_path + "/clang++"
env["AR"] = compiler_path + "/llvm-ar"
env["RANLIB"] = compiler_path + "/llvm-ranlib"
- env["AS"] = bin_utils_path + "/as"
+ env["AS"] = compiler_path + "/clang"
# Disable exceptions and rtti on non-tools (template) builds
if env["tools"]:
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 5b9eee8117..eb344d3b43 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -31,30 +31,32 @@
#include "dir_access_jandroid.h"
#include "core/string/print_string.h"
-#include "file_access_android.h"
#include "string_android.h"
#include "thread_jandroid.h"
-jobject DirAccessJAndroid::io = nullptr;
+jobject DirAccessJAndroid::dir_access_handler = nullptr;
jclass DirAccessJAndroid::cls = nullptr;
jmethodID DirAccessJAndroid::_dir_open = nullptr;
jmethodID DirAccessJAndroid::_dir_next = nullptr;
jmethodID DirAccessJAndroid::_dir_close = nullptr;
jmethodID DirAccessJAndroid::_dir_is_dir = nullptr;
-
-Ref<DirAccess> DirAccessJAndroid::create_fs() {
- return memnew(DirAccessJAndroid);
-}
+jmethodID DirAccessJAndroid::_dir_exists = nullptr;
+jmethodID DirAccessJAndroid::_file_exists = nullptr;
+jmethodID DirAccessJAndroid::_get_drive_count = nullptr;
+jmethodID DirAccessJAndroid::_get_drive = nullptr;
+jmethodID DirAccessJAndroid::_make_dir = nullptr;
+jmethodID DirAccessJAndroid::_get_space_left = nullptr;
+jmethodID DirAccessJAndroid::_rename = nullptr;
+jmethodID DirAccessJAndroid::_remove = nullptr;
+jmethodID DirAccessJAndroid::_current_is_hidden = nullptr;
Error DirAccessJAndroid::list_dir_begin() {
list_dir_end();
- JNIEnv *env = get_jni_env();
-
- jstring js = env->NewStringUTF(current_dir.utf8().get_data());
- int res = env->CallIntMethod(io, _dir_open, js);
+ int res = dir_open(current_dir);
if (res <= 0) {
return ERR_CANT_OPEN;
}
+
id = res;
return OK;
@@ -62,169 +64,236 @@ Error DirAccessJAndroid::list_dir_begin() {
String DirAccessJAndroid::get_next() {
ERR_FAIL_COND_V(id == 0, "");
+ if (_dir_next) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, "");
+ jstring str = (jstring)env->CallObjectMethod(dir_access_handler, _dir_next, get_access_type(), id);
+ if (!str) {
+ return "";
+ }
- JNIEnv *env = get_jni_env();
- jstring str = (jstring)env->CallObjectMethod(io, _dir_next, id);
- if (!str) {
+ String ret = jstring_to_string((jstring)str, env);
+ env->DeleteLocalRef((jobject)str);
+ return ret;
+ } else {
return "";
}
- String ret = jstring_to_string((jstring)str, env);
- env->DeleteLocalRef((jobject)str);
- return ret;
}
bool DirAccessJAndroid::current_is_dir() const {
- JNIEnv *env = get_jni_env();
-
- return env->CallBooleanMethod(io, _dir_is_dir, id);
+ if (_dir_is_dir) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+ return env->CallBooleanMethod(dir_access_handler, _dir_is_dir, get_access_type(), id);
+ } else {
+ return false;
+ }
}
bool DirAccessJAndroid::current_is_hidden() const {
- return current != "." && current != ".." && current.begins_with(".");
+ if (_current_is_hidden) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+ return env->CallBooleanMethod(dir_access_handler, _current_is_hidden, get_access_type(), id);
+ }
+ return false;
}
void DirAccessJAndroid::list_dir_end() {
if (id == 0) {
return;
}
- JNIEnv *env = get_jni_env();
- env->CallVoidMethod(io, _dir_close, id);
+
+ dir_close(id);
id = 0;
}
int DirAccessJAndroid::get_drive_count() {
- return 0;
+ if (_get_drive_count) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+ return env->CallIntMethod(dir_access_handler, _get_drive_count, get_access_type());
+ } else {
+ return 0;
+ }
}
String DirAccessJAndroid::get_drive(int p_drive) {
- return "";
+ if (_get_drive) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, "");
+ jstring j_drive = (jstring)env->CallObjectMethod(dir_access_handler, _get_drive, get_access_type(), p_drive);
+ if (!j_drive) {
+ return "";
+ }
+
+ String drive = jstring_to_string(j_drive, env);
+ env->DeleteLocalRef(j_drive);
+ return drive;
+ } else {
+ return "";
+ }
}
Error DirAccessJAndroid::change_dir(String p_dir) {
- JNIEnv *env = get_jni_env();
-
- if (p_dir.is_empty() || p_dir == "." || (p_dir == ".." && current_dir.is_empty())) {
+ String new_dir = get_absolute_path(p_dir);
+ if (new_dir == current_dir) {
return OK;
}
- String new_dir;
-
- if (p_dir != "res://" && p_dir.length() > 1 && p_dir.ends_with("/")) {
- p_dir = p_dir.substr(0, p_dir.length() - 1);
- }
-
- if (p_dir.begins_with("/")) {
- new_dir = p_dir.substr(1, p_dir.length());
- } else if (p_dir.begins_with("res://")) {
- new_dir = p_dir.substr(6, p_dir.length());
- } else if (current_dir.is_empty()) {
- new_dir = p_dir;
- } else {
- new_dir = current_dir.plus_file(p_dir);
- }
-
- //test if newdir exists
- new_dir = new_dir.simplify_path();
-
- jstring js = env->NewStringUTF(new_dir.utf8().get_data());
- int res = env->CallIntMethod(io, _dir_open, js);
- env->DeleteLocalRef(js);
- if (res <= 0) {
+ if (!dir_exists(new_dir)) {
return ERR_INVALID_PARAMETER;
}
- env->CallVoidMethod(io, _dir_close, res);
-
current_dir = new_dir;
-
return OK;
}
-String DirAccessJAndroid::get_current_dir(bool p_include_drive) const {
- return "res://" + current_dir;
+String DirAccessJAndroid::get_absolute_path(String p_path) {
+ if (current_dir != "" && p_path == current_dir) {
+ return current_dir;
+ }
+
+ if (p_path.is_relative_path()) {
+ p_path = get_current_dir().plus_file(p_path);
+ }
+
+ p_path = fix_path(p_path);
+ p_path = p_path.simplify_path();
+ return p_path;
}
bool DirAccessJAndroid::file_exists(String p_file) {
- String sd;
- if (current_dir.is_empty()) {
- sd = p_file;
+ if (_file_exists) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
+ String path = get_absolute_path(p_file);
+ jstring j_path = env->NewStringUTF(path.utf8().get_data());
+ bool result = env->CallBooleanMethod(dir_access_handler, _file_exists, get_access_type(), j_path);
+ env->DeleteLocalRef(j_path);
+ return result;
} else {
- sd = current_dir.plus_file(p_file);
+ return false;
}
-
- Ref<FileAccessAndroid> f;
- f.instantiate();
- bool exists = f->file_exists(sd);
-
- return exists;
}
bool DirAccessJAndroid::dir_exists(String p_dir) {
- JNIEnv *env = get_jni_env();
-
- String sd;
-
- if (current_dir.is_empty()) {
- sd = p_dir;
+ if (_dir_exists) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
+ String path = get_absolute_path(p_dir);
+ jstring j_path = env->NewStringUTF(path.utf8().get_data());
+ bool result = env->CallBooleanMethod(dir_access_handler, _dir_exists, get_access_type(), j_path);
+ env->DeleteLocalRef(j_path);
+ return result;
} else {
- if (p_dir.is_relative_path()) {
- sd = current_dir.plus_file(p_dir);
- } else {
- sd = fix_path(p_dir);
- }
- }
-
- String path = sd.simplify_path();
-
- if (path.begins_with("/")) {
- path = path.substr(1, path.length());
- } else if (path.begins_with("res://")) {
- path = path.substr(6, path.length());
+ return false;
}
+}
- jstring js = env->NewStringUTF(path.utf8().get_data());
- int res = env->CallIntMethod(io, _dir_open, js);
- env->DeleteLocalRef(js);
- if (res <= 0) {
- return false;
+Error DirAccessJAndroid::make_dir_recursive(String p_dir) {
+ // Check if the directory exists already
+ if (dir_exists(p_dir)) {
+ return ERR_ALREADY_EXISTS;
}
- env->CallVoidMethod(io, _dir_close, res);
+ if (_make_dir) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
- return true;
+ String path = get_absolute_path(p_dir);
+ jstring j_dir = env->NewStringUTF(path.utf8().get_data());
+ bool result = env->CallBooleanMethod(dir_access_handler, _make_dir, get_access_type(), j_dir);
+ env->DeleteLocalRef(j_dir);
+ if (result) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+ } else {
+ return ERR_UNCONFIGURED;
+ }
}
Error DirAccessJAndroid::make_dir(String p_dir) {
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ return make_dir_recursive(p_dir);
}
Error DirAccessJAndroid::rename(String p_from, String p_to) {
- ERR_FAIL_V(ERR_UNAVAILABLE);
-}
+ if (_rename) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
-Error DirAccessJAndroid::remove(String p_name) {
- ERR_FAIL_V(ERR_UNAVAILABLE);
+ String from_path = get_absolute_path(p_from);
+ jstring j_from = env->NewStringUTF(from_path.utf8().get_data());
+
+ String to_path = get_absolute_path(p_to);
+ jstring j_to = env->NewStringUTF(to_path.utf8().get_data());
+
+ bool result = env->CallBooleanMethod(dir_access_handler, _rename, get_access_type(), j_from, j_to);
+ env->DeleteLocalRef(j_from);
+ env->DeleteLocalRef(j_to);
+ if (result) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+ } else {
+ return ERR_UNCONFIGURED;
+ }
}
-String DirAccessJAndroid::get_filesystem_type() const {
- return "APK";
+Error DirAccessJAndroid::remove(String p_name) {
+ if (_remove) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+
+ String path = get_absolute_path(p_name);
+ jstring j_name = env->NewStringUTF(path.utf8().get_data());
+ bool result = env->CallBooleanMethod(dir_access_handler, _remove, get_access_type(), j_name);
+ env->DeleteLocalRef(j_name);
+ if (result) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+ } else {
+ return ERR_UNCONFIGURED;
+ }
}
uint64_t DirAccessJAndroid::get_space_left() {
- return 0;
+ if (_get_space_left) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+ return env->CallLongMethod(dir_access_handler, _get_space_left, get_access_type());
+ } else {
+ return 0;
+ }
}
-void DirAccessJAndroid::setup(jobject p_io) {
+void DirAccessJAndroid::setup(jobject p_dir_access_handler) {
JNIEnv *env = get_jni_env();
- io = p_io;
+ dir_access_handler = env->NewGlobalRef(p_dir_access_handler);
- jclass c = env->GetObjectClass(io);
+ jclass c = env->GetObjectClass(dir_access_handler);
cls = (jclass)env->NewGlobalRef(c);
- _dir_open = env->GetMethodID(cls, "dir_open", "(Ljava/lang/String;)I");
- _dir_next = env->GetMethodID(cls, "dir_next", "(I)Ljava/lang/String;");
- _dir_close = env->GetMethodID(cls, "dir_close", "(I)V");
- _dir_is_dir = env->GetMethodID(cls, "dir_is_dir", "(I)Z");
+ _dir_open = env->GetMethodID(cls, "dirOpen", "(ILjava/lang/String;)I");
+ _dir_next = env->GetMethodID(cls, "dirNext", "(II)Ljava/lang/String;");
+ _dir_close = env->GetMethodID(cls, "dirClose", "(II)V");
+ _dir_is_dir = env->GetMethodID(cls, "dirIsDir", "(II)Z");
+ _dir_exists = env->GetMethodID(cls, "dirExists", "(ILjava/lang/String;)Z");
+ _file_exists = env->GetMethodID(cls, "fileExists", "(ILjava/lang/String;)Z");
+ _get_drive_count = env->GetMethodID(cls, "getDriveCount", "(I)I");
+ _get_drive = env->GetMethodID(cls, "getDrive", "(II)Ljava/lang/String;");
+ _make_dir = env->GetMethodID(cls, "makeDir", "(ILjava/lang/String;)Z");
+ _get_space_left = env->GetMethodID(cls, "getSpaceLeft", "(I)J");
+ _rename = env->GetMethodID(cls, "rename", "(ILjava/lang/String;Ljava/lang/String;)Z");
+ _remove = env->GetMethodID(cls, "remove", "(ILjava/lang/String;)Z");
+ _current_is_hidden = env->GetMethodID(cls, "isCurrentHidden", "(II)Z");
}
DirAccessJAndroid::DirAccessJAndroid() {
@@ -233,3 +302,26 @@ DirAccessJAndroid::DirAccessJAndroid() {
DirAccessJAndroid::~DirAccessJAndroid() {
list_dir_end();
}
+
+int DirAccessJAndroid::dir_open(String p_path) {
+ if (_dir_open) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+
+ String path = get_absolute_path(p_path);
+ jstring js = env->NewStringUTF(path.utf8().get_data());
+ int dirId = env->CallIntMethod(dir_access_handler, _dir_open, get_access_type(), js);
+ env->DeleteLocalRef(js);
+ return dirId;
+ } else {
+ return 0;
+ }
+}
+
+void DirAccessJAndroid::dir_close(int p_id) {
+ if (_dir_close) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+ env->CallVoidMethod(dir_access_handler, _dir_close, get_access_type(), p_id);
+ }
+}
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index 0e1b12cb58..d469c9d317 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -32,58 +32,70 @@
#define DIR_ACCESS_JANDROID_H
#include "core/io/dir_access.h"
+#include "drivers/unix/dir_access_unix.h"
#include "java_godot_lib_jni.h"
#include <stdio.h>
-class DirAccessJAndroid : public DirAccess {
- static jobject io;
+/// Android implementation of the DirAccess interface used to provide access to
+/// ACCESS_FILESYSTEM and ACCESS_RESOURCES directory resources.
+/// The implementation use jni in order to comply with Android filesystem
+/// access restriction.
+class DirAccessJAndroid : public DirAccessUnix {
+ static jobject dir_access_handler;
static jclass cls;
static jmethodID _dir_open;
static jmethodID _dir_next;
static jmethodID _dir_close;
static jmethodID _dir_is_dir;
-
- int id = 0;
-
- String current_dir;
- String current;
-
- static Ref<DirAccess> create_fs();
+ static jmethodID _dir_exists;
+ static jmethodID _file_exists;
+ static jmethodID _get_drive_count;
+ static jmethodID _get_drive;
+ static jmethodID _make_dir;
+ static jmethodID _get_space_left;
+ static jmethodID _rename;
+ static jmethodID _remove;
+ static jmethodID _current_is_hidden;
public:
- virtual Error list_dir_begin(); ///< This starts dir listing
- virtual String get_next();
- virtual bool current_is_dir() const;
- virtual bool current_is_hidden() const;
- virtual void list_dir_end(); ///<
+ virtual Error list_dir_begin() override; ///< This starts dir listing
+ virtual String get_next() override;
+ virtual bool current_is_dir() const override;
+ virtual bool current_is_hidden() const override;
+ virtual void list_dir_end() override; ///<
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
+ virtual int get_drive_count() override;
+ virtual String get_drive(int p_drive) override;
- virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
+ virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
- virtual bool file_exists(String p_file);
- virtual bool dir_exists(String p_dir);
+ virtual bool file_exists(String p_file) override;
+ virtual bool dir_exists(String p_dir) override;
- virtual Error make_dir(String p_dir);
+ virtual Error make_dir(String p_dir) override;
+ virtual Error make_dir_recursive(String p_dir) override;
- virtual Error rename(String p_from, String p_to);
- virtual Error remove(String p_name);
+ virtual Error rename(String p_from, String p_to) override;
+ virtual Error remove(String p_name) override;
- virtual bool is_link(String p_file) { return false; }
- virtual String read_link(String p_file) { return p_file; }
- virtual Error create_link(String p_source, String p_target) { return FAILED; }
+ virtual bool is_link(String p_file) override { return false; }
+ virtual String read_link(String p_file) override { return p_file; }
+ virtual Error create_link(String p_source, String p_target) override { return FAILED; }
- virtual String get_filesystem_type() const;
+ virtual uint64_t get_space_left() override;
- uint64_t get_space_left();
-
- static void setup(jobject p_io);
+ static void setup(jobject p_dir_access_handler);
DirAccessJAndroid();
~DirAccessJAndroid();
+
+private:
+ int id = 0;
+
+ int dir_open(String p_path);
+ void dir_close(int p_id);
+ String get_absolute_path(String p_path);
};
#endif // DIR_ACCESS_JANDROID_H
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index b40c1f5090..2cfb152804 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -123,6 +123,7 @@ static const char *android_perms[] = {
"MANAGE_ACCOUNTS",
"MANAGE_APP_TOKENS",
"MANAGE_DOCUMENTS",
+ "MANAGE_EXTERNAL_STORAGE",
"MASTER_CLEAR",
"MEDIA_CONTENT_CONTROL",
"MODIFY_AUDIO_SETTINGS",
@@ -245,8 +246,7 @@ static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets";
static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets";
static const int DEFAULT_MIN_SDK_VERSION = 19; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
-static const int DEFAULT_TARGET_SDK_VERSION = 31; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
-const String SDK_VERSION_RANGE = vformat("%s,%s,1", DEFAULT_MIN_SDK_VERSION, DEFAULT_TARGET_SDK_VERSION);
+static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
EditorExportPlatformAndroid *ea = static_cast<EditorExportPlatformAndroid *>(ud);
@@ -277,6 +277,7 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
}
}
+#ifndef ANDROID_ENABLED
// Check for devices updates
String adb = get_adb_path();
if (FileAccess::exists(adb)) {
@@ -388,6 +389,7 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
ea->devices_changed.set();
}
}
+#endif
uint64_t sleep = 200;
uint64_t wait = 3000000;
@@ -400,6 +402,7 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
}
}
+#ifndef ANDROID_ENABLED
if (EditorSettings::get_singleton()->get("export/android/shutdown_adb_on_exit")) {
String adb = get_adb_path();
if (!FileAccess::exists(adb)) {
@@ -410,6 +413,7 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) {
args.push_back("kill-server");
OS::get_singleton()->execute(adb, args);
}
+#endif
}
String EditorExportPlatformAndroid::get_project_name(const String &p_name) const {
@@ -748,10 +752,14 @@ Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const Shared
return OK;
}
-bool EditorExportPlatformAndroid::_has_storage_permission(const Vector<String> &p_permissions) {
+bool EditorExportPlatformAndroid::_has_read_write_storage_permission(const Vector<String> &p_permissions) {
return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1;
}
+bool EditorExportPlatformAndroid::_has_manage_external_storage_permission(const Vector<String> &p_permissions) {
+ return p_permissions.find("android.permission.MANAGE_EXTERNAL_STORAGE") != -1;
+}
+
void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
const char **aperms = android_perms;
while (*aperms) {
@@ -799,7 +807,7 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
_get_permissions(p_preset, p_give_internet, perms);
for (int i = 0; i < perms.size(); i++) {
String permission = perms.get(i);
- if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || permission == "android.permission.READ_EXTERNAL_STORAGE") {
+ if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || (permission == "android.permission.READ_EXTERNAL_STORAGE" && _has_manage_external_storage_permission(perms))) {
manifest_text += vformat(" <uses-permission android:name=\"%s\" android:maxSdkVersion=\"29\" />\n", permission);
} else {
manifest_text += vformat(" <uses-permission android:name=\"%s\" />\n", permission);
@@ -807,7 +815,7 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
}
manifest_text += _get_xr_features_tag(p_preset);
- manifest_text += _get_application_tag(p_preset, _has_storage_permission(perms));
+ manifest_text += _get_application_tag(p_preset, _has_read_write_storage_permission(perms));
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
@@ -865,7 +873,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
Vector<String> perms;
// Write permissions into the perms variable.
_get_permissions(p_preset, p_give_internet, perms);
- bool has_storage_permission = _has_storage_permission(perms);
+ bool has_read_write_storage_permission = _has_read_write_storage_permission(perms);
while (ofs < (uint32_t)p_manifest.size()) {
uint32_t chunk = decode_uint32(&p_manifest[ofs]);
@@ -949,7 +957,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
if (tname == "application" && attrname == "requestLegacyExternalStorage") {
- encode_uint32(has_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
+ encode_uint32(has_read_write_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
}
if (tname == "application" && attrname == "allowBackup") {
@@ -1682,8 +1690,13 @@ void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPres
void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_options) {
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_template/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_build/use_custom_build"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
+ // Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
+ // This implies doing validation that the string is a proper int.
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
for (int i = 0; i < plugins_configs.size(); i++) {
@@ -1710,8 +1723,6 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/min_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_MIN_SDK_VERSION));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/target_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_TARGET_SDK_VERSION));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
@@ -2039,7 +2050,7 @@ String EditorExportPlatformAndroid::get_apksigner_path() {
bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
bool valid = false;
- const bool custom_build_enabled = p_preset->get("custom_template/use_custom_build");
+ const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build");
// Look for export templates (first official, and if defined custom templates).
@@ -2201,43 +2212,73 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
if (xr_mode_index != XR_MODE_OPENXR) {
if (hand_tracking > XR_HAND_TRACKING_NONE) {
valid = false;
- err += TTR("\"Hand Tracking\" is only valid when \"Xr Mode\" is \"OpenXR\".");
+ err += TTR("\"Hand Tracking\" is only valid when \"XR Mode\" is \"OpenXR\".");
err += "\n";
}
if (passthrough_mode > XR_PASSTHROUGH_NONE) {
valid = false;
- err += TTR("\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\".");
+ err += TTR("\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\".");
err += "\n";
}
}
- if (int(p_preset->get("custom_template/export_format")) == EXPORT_FORMAT_AAB &&
+ if (int(p_preset->get("custom_build/export_format")) == EXPORT_FORMAT_AAB &&
!custom_build_enabled) {
valid = false;
err += TTR("\"Export AAB\" is only valid when \"Use Custom Build\" is enabled.");
err += "\n";
}
- // Check the min sdk version
- int min_sdk_version = p_preset->get("version/min_sdk");
- if (min_sdk_version != DEFAULT_MIN_SDK_VERSION && !custom_build_enabled) {
- valid = false;
- err += TTR("Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled.");
- err += "\n";
+ // Check the min sdk version.
+ String min_sdk_str = p_preset->get("custom_build/min_sdk");
+ int min_sdk_int = DEFAULT_MIN_SDK_VERSION;
+ if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
+ if (!custom_build_enabled) {
+ valid = false;
+ err += TTR("\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
+ err += "\n";
+ }
+ if (!min_sdk_str.is_valid_int()) {
+ valid = false;
+ err += vformat(TTR("\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."), min_sdk_str);
+ err += "\n";
+ } else {
+ min_sdk_int = min_sdk_str.to_int();
+ if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) {
+ valid = false;
+ err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION);
+ err += "\n";
+ }
+ }
}
- // Check the target sdk version
- int target_sdk_version = p_preset->get("version/target_sdk");
- if (target_sdk_version != DEFAULT_TARGET_SDK_VERSION && !custom_build_enabled) {
- valid = false;
- err += TTR("Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is enabled.");
- err += "\n";
+ // Check the target sdk version.
+ String target_sdk_str = p_preset->get("custom_build/target_sdk");
+ int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
+ if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
+ if (!custom_build_enabled) {
+ valid = false;
+ err += TTR("\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
+ err += "\n";
+ }
+ if (!target_sdk_str.is_valid_int()) {
+ valid = false;
+ err += vformat(TTR("\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."), target_sdk_str);
+ err += "\n";
+ } else {
+ target_sdk_int = target_sdk_str.to_int();
+ if (target_sdk_int > DEFAULT_TARGET_SDK_VERSION) {
+ // Warning only, so don't override `valid`.
+ err += vformat(TTR("\"Target SDK\" %d is higher than the default version %d. This may work, but wasn't tested and may be unstable."), target_sdk_int, DEFAULT_TARGET_SDK_VERSION);
+ err += "\n";
+ }
+ }
}
- if (target_sdk_version < min_sdk_version) {
+ if (target_sdk_int < min_sdk_int) {
valid = false;
- err += TTR("\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version.");
+ err += TTR("\"Target SDK\" version must be greater or equal to \"Min SDK\" version.");
err += "\n";
}
@@ -2326,7 +2367,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
}
Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) {
- int export_format = int(p_preset->get("custom_template/export_format"));
+ int export_format = int(p_preset->get("custom_build/export_format"));
String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK";
String release_keystore = p_preset->get("keystore/release");
String release_username = p_preset->get("keystore/release_user");
@@ -2482,7 +2523,7 @@ String EditorExportPlatformAndroid::join_list(List<String> parts, const String &
}
Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- int export_format = int(p_preset->get("custom_template/export_format"));
+ int export_format = int(p_preset->get("custom_build/export_format"));
bool should_sign = p_preset->get("package/signed");
return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags);
}
@@ -2495,7 +2536,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
EditorProgress ep("export", TTR("Exporting for Android"), 105, true);
- bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build"));
+ bool use_custom_build = bool(p_preset->get("custom_build/use_custom_build"));
bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG);
bool apk_expansion = p_preset->get("apk_expansion/enable");
Vector<String> enabled_abis = get_enabled_abis(p_preset);
@@ -2623,8 +2664,14 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String package_name = get_package_name(p_preset->get("package/unique_name"));
String version_code = itos(p_preset->get("version/code"));
String version_name = p_preset->get("version/name");
- String min_sdk_version = itos(p_preset->get("version/min_sdk"));
- String target_sdk_version = itos(p_preset->get("version/target_sdk"));
+ String min_sdk_version = p_preset->get("custom_build/min_sdk");
+ if (!min_sdk_version.is_valid_int()) {
+ min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION);
+ }
+ String target_sdk_version = p_preset->get("custom_build/target_sdk");
+ if (!target_sdk_version.is_valid_int()) {
+ target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
+ }
String enabled_abi_string = String("|").join(enabled_abis);
String sign_flag = should_sign ? "true" : "false";
String zipalign_flag = "true";
@@ -3071,13 +3118,8 @@ void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<
}
EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
- Ref<Image> img = memnew(Image(_android_logo));
- logo.instantiate();
- logo->create_from_image(img);
-
- img = Ref<Image>(memnew(Image(_android_run_icon)));
- run_icon.instantiate();
- run_icon->create_from_image(img);
+ logo = ImageTexture::create_from_image(memnew(Image(_android_logo)));
+ run_icon = ImageTexture::create_from_image(memnew(Image(_android_run_icon)));
devices_changed.set();
plugins_changed.set();
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index eeb5aae0f1..15ac8091be 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -116,7 +116,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so);
- bool _has_storage_permission(const Vector<String> &p_permissions);
+ bool _has_read_write_storage_permission(const Vector<String> &p_permissions);
+
+ bool _has_manage_external_storage_permission(const Vector<String> &p_permissions);
void _get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions);
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 9a470edfdd..8d370a31a4 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -254,7 +254,7 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_activity_text;
}
-String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission) {
+String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission) {
int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
String manifest_application_text = vformat(
@@ -271,7 +271,7 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
bool_to_string(p_preset->get("user_data_backup/allow")),
bool_to_string(p_preset->get("package/classify_as_game")),
bool_to_string(p_preset->get("package/retain_data_on_uninstall")),
- bool_to_string(p_has_storage_permission));
+ bool_to_string(p_has_read_write_storage_permission));
if (uses_xr) {
bool hand_tracking_enabled = (int)(p_preset->get("xr_features/hand_tracking")) > XR_HAND_TRACKING_NONE;
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 109852bdfc..7896392d16 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -104,6 +104,6 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset);
String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
-String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission);
+String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission);
#endif // GODOT_GRADLE_EXPORT_UTIL_H
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 4bb8a13bb6..ace7636e6c 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -34,14 +34,20 @@
AAssetManager *FileAccessAndroid::asset_manager = nullptr;
-Ref<FileAccess> FileAccessAndroid::create_android() {
- return memnew(FileAccessAndroid);
+String FileAccessAndroid::get_path() const {
+ return path_src;
+}
+
+String FileAccessAndroid::get_path_absolute() const {
+ return absolute_path;
}
Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) {
_close();
+ path_src = p_path;
String path = fix_path(p_path).simplify_path();
+ absolute_path = path;
if (path.begins_with("/")) {
path = path.substr(1, path.length());
} else if (path.begins_with("res://")) {
@@ -134,7 +140,7 @@ uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const
}
Error FileAccessAndroid::get_error() const {
- return eof ? ERR_FILE_EOF : OK; //not sure what else it may happen
+ return eof ? ERR_FILE_EOF : OK; // not sure what else it may happen
}
void FileAccessAndroid::flush() {
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index c16f74ac43..e6fd8c857b 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -37,11 +37,12 @@
#include <stdio.h>
class FileAccessAndroid : public FileAccess {
- static Ref<FileAccess> create_android();
mutable AAsset *asset = nullptr;
mutable uint64_t len = 0;
mutable uint64_t pos = 0;
mutable bool eof = false;
+ String absolute_path;
+ String path_src;
void _close();
@@ -51,6 +52,11 @@ public:
virtual Error _open(const String &p_path, int p_mode_flags); // open a file
virtual bool is_open() const; // true when file is open
+ /// returns the path for the current open file
+ virtual String get_path() const;
+ /// returns the absolute path for the current open file
+ virtual String get_path_absolute() const;
+
virtual void seek(uint64_t p_position); // seek to a given position
virtual void seek_end(int64_t p_position = 0); // seek from the end of file
virtual uint64_t get_position() const; // get position in the file
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
new file mode 100644
index 0000000000..c1a48e025e
--- /dev/null
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -0,0 +1,283 @@
+/*************************************************************************/
+/* file_access_filesystem_jandroid.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "file_access_filesystem_jandroid.h"
+#include "core/os/os.h"
+#include "thread_jandroid.h"
+#include <unistd.h>
+
+jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr;
+jclass FileAccessFilesystemJAndroid::cls;
+
+jmethodID FileAccessFilesystemJAndroid::_file_open = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_get_size = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_seek = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_seek_end = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_read = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_tell = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_eof = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_close = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_write = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_flush = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_exists = nullptr;
+jmethodID FileAccessFilesystemJAndroid::_file_last_modified = nullptr;
+
+String FileAccessFilesystemJAndroid::get_path() const {
+ return path_src;
+}
+
+String FileAccessFilesystemJAndroid::get_path_absolute() const {
+ return absolute_path;
+}
+
+Error FileAccessFilesystemJAndroid::_open(const String &p_path, int p_mode_flags) {
+ if (is_open()) {
+ _close();
+ }
+
+ if (_file_open) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED);
+
+ String path = fix_path(p_path).simplify_path();
+ jstring js = env->NewStringUTF(path.utf8().get_data());
+ int res = env->CallIntMethod(file_access_handler, _file_open, js, p_mode_flags);
+ env->DeleteLocalRef(js);
+
+ if (res <= 0) {
+ switch (res) {
+ case 0:
+ default:
+ return ERR_FILE_CANT_OPEN;
+
+ case -1:
+ return ERR_FILE_NOT_FOUND;
+ }
+ }
+
+ id = res;
+ path_src = p_path;
+ absolute_path = path;
+ return OK;
+ } else {
+ return ERR_UNCONFIGURED;
+ }
+}
+
+void FileAccessFilesystemJAndroid::_close() {
+ if (!is_open()) {
+ return;
+ }
+
+ if (_file_close) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+ env->CallVoidMethod(file_access_handler, _file_close, id);
+ }
+ id = 0;
+}
+
+bool FileAccessFilesystemJAndroid::is_open() const {
+ return id != 0;
+}
+
+void FileAccessFilesystemJAndroid::seek(uint64_t p_position) {
+ if (_file_seek) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
+ env->CallVoidMethod(file_access_handler, _file_seek, id, p_position);
+ }
+}
+
+void FileAccessFilesystemJAndroid::seek_end(int64_t p_position) {
+ if (_file_seek_end) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
+ env->CallVoidMethod(file_access_handler, _file_seek_end, id, p_position);
+ }
+}
+
+uint64_t FileAccessFilesystemJAndroid::get_position() const {
+ if (_file_tell) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ return env->CallLongMethod(file_access_handler, _file_tell, id);
+ } else {
+ return 0;
+ }
+}
+
+uint64_t FileAccessFilesystemJAndroid::get_length() const {
+ if (_file_get_size) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ return env->CallLongMethod(file_access_handler, _file_get_size, id);
+ } else {
+ return 0;
+ }
+}
+
+bool FileAccessFilesystemJAndroid::eof_reached() const {
+ if (_file_eof) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+ ERR_FAIL_COND_V_MSG(!is_open(), false, "File must be opened before use.");
+ return env->CallBooleanMethod(file_access_handler, _file_eof, id);
+ } else {
+ return false;
+ }
+}
+
+uint8_t FileAccessFilesystemJAndroid::get_8() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint8_t byte;
+ get_buffer(&byte, 1);
+ return byte;
+}
+
+uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+ if (_file_read) {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ if (p_length == 0) {
+ return 0;
+ }
+
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 0);
+
+ jobject j_buffer = env->NewDirectByteBuffer(p_dst, p_length);
+ int length = env->CallIntMethod(file_access_handler, _file_read, id, j_buffer);
+ env->DeleteLocalRef(j_buffer);
+ return length;
+ } else {
+ return 0;
+ }
+}
+
+void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
+ store_buffer(&p_dest, 1);
+}
+
+void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
+ if (_file_write) {
+ ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
+ if (p_length == 0) {
+ return;
+ }
+
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+
+ jobject j_buffer = env->NewDirectByteBuffer((void *)p_src, p_length);
+ env->CallVoidMethod(file_access_handler, _file_write, id, j_buffer);
+ env->DeleteLocalRef(j_buffer);
+ }
+}
+
+Error FileAccessFilesystemJAndroid::get_error() const {
+ if (eof_reached()) {
+ return ERR_FILE_EOF;
+ }
+ return OK;
+}
+
+void FileAccessFilesystemJAndroid::flush() {
+ if (_file_flush) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND(env == nullptr);
+ ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
+ env->CallVoidMethod(file_access_handler, _file_flush, id);
+ }
+}
+
+bool FileAccessFilesystemJAndroid::file_exists(const String &p_path) {
+ if (_file_exists) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
+ String path = fix_path(p_path).simplify_path();
+ jstring js = env->NewStringUTF(path.utf8().get_data());
+ bool result = env->CallBooleanMethod(file_access_handler, _file_exists, js);
+ env->DeleteLocalRef(js);
+ return result;
+ } else {
+ return false;
+ }
+}
+
+uint64_t FileAccessFilesystemJAndroid::_get_modified_time(const String &p_file) {
+ if (_file_last_modified) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, false);
+
+ String path = fix_path(p_file).simplify_path();
+ jstring js = env->NewStringUTF(path.utf8().get_data());
+ uint64_t result = env->CallLongMethod(file_access_handler, _file_last_modified, js);
+ env->DeleteLocalRef(js);
+ return result;
+ } else {
+ return 0;
+ }
+}
+
+void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) {
+ JNIEnv *env = get_jni_env();
+ file_access_handler = env->NewGlobalRef(p_file_access_handler);
+
+ jclass c = env->GetObjectClass(file_access_handler);
+ cls = (jclass)env->NewGlobalRef(c);
+
+ _file_open = env->GetMethodID(cls, "fileOpen", "(Ljava/lang/String;I)I");
+ _file_get_size = env->GetMethodID(cls, "fileGetSize", "(I)J");
+ _file_tell = env->GetMethodID(cls, "fileGetPosition", "(I)J");
+ _file_eof = env->GetMethodID(cls, "isFileEof", "(I)Z");
+ _file_seek = env->GetMethodID(cls, "fileSeek", "(IJ)V");
+ _file_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V");
+ _file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I");
+ _file_close = env->GetMethodID(cls, "fileClose", "(I)V");
+ _file_write = env->GetMethodID(cls, "fileWrite", "(ILjava/nio/ByteBuffer;)V");
+ _file_flush = env->GetMethodID(cls, "fileFlush", "(I)V");
+ _file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z");
+ _file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
+}
+
+FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() {
+ id = 0;
+}
+
+FileAccessFilesystemJAndroid::~FileAccessFilesystemJAndroid() {
+ if (is_open()) {
+ _close();
+ }
+}
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
new file mode 100644
index 0000000000..18d5df1628
--- /dev/null
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -0,0 +1,97 @@
+/*************************************************************************/
+/* file_access_filesystem_jandroid.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FILE_ACCESS_FILESYSTEM_JANDROID_H
+#define FILE_ACCESS_FILESYSTEM_JANDROID_H
+
+#include "core/io/file_access.h"
+#include "java_godot_lib_jni.h"
+
+class FileAccessFilesystemJAndroid : public FileAccess {
+ static jobject file_access_handler;
+ static jclass cls;
+
+ static jmethodID _file_open;
+ static jmethodID _file_get_size;
+ static jmethodID _file_seek;
+ static jmethodID _file_seek_end;
+ static jmethodID _file_tell;
+ static jmethodID _file_eof;
+ static jmethodID _file_read;
+ static jmethodID _file_write;
+ static jmethodID _file_flush;
+ static jmethodID _file_close;
+ static jmethodID _file_exists;
+ static jmethodID _file_last_modified;
+
+ int id;
+ String absolute_path;
+ String path_src;
+
+ void _close(); ///< close a file
+
+public:
+ virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual bool is_open() const override; ///< true when file is open
+
+ /// returns the path for the current open file
+ virtual String get_path() const override;
+ /// returns the absolute path for the current open file
+ virtual String get_path_absolute() const override;
+
+ virtual void seek(uint64_t p_position) override; ///< seek to a given position
+ virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
+ virtual uint64_t get_position() const override; ///< get position in the file
+ virtual uint64_t get_length() const override; ///< get size of the file
+
+ virtual bool eof_reached() const override; ///< reading passed EOF
+
+ virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
+
+ virtual Error get_error() const override; ///< get last error
+
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
+
+ virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
+
+ static void setup(jobject p_file_access_handler);
+
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+
+ FileAccessFilesystemJAndroid();
+ ~FileAccessFilesystemJAndroid();
+};
+
+#endif // FILE_ACCESS_FILESYSTEM_JANDROID_H
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 3daf628e63..fbd97fae0b 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -1,9 +1,9 @@
ext.versions = [
androidGradlePlugin: '7.0.3',
- compileSdk : 31,
+ compileSdk : 32,
minSdk : 19, // Also update 'platform/android/java/lib/AndroidManifest.xml#minSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION'
- targetSdk : 31, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
- buildTools : '30.0.3',
+ targetSdk : 32, // Also update 'platform/android/java/lib/AndroidManifest.xml#targetSdkVersion' & 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION'
+ buildTools : '32.0.0',
kotlinVersion : '1.6.21',
fragmentVersion : '1.3.6',
nexusPublishVersion: '1.1.0',
diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle
index dd167c3880..729966ee69 100644
--- a/platform/android/java/editor/build.gradle
+++ b/platform/android/java/editor/build.gradle
@@ -23,8 +23,7 @@ android {
versionCode getGodotLibraryVersionCode()
versionName getGodotLibraryVersionName()
minSdkVersion versions.minSdk
- //noinspection ExpiredTargetSdkVersion - Restrict to version 29 until https://github.com/godotengine/godot/pull/51815 is submitted
- targetSdkVersion 29 // versions.targetSdk
+ targetSdkVersion versions.targetSdk
missingDimensionStrategy 'products', 'editor'
}
diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml
index 93cbb47400..abf506a83c 100644
--- a/platform/android/java/editor/src/main/AndroidManifest.xml
+++ b/platform/android/java/editor/src/main/AndroidManifest.xml
@@ -14,8 +14,12 @@
android:glEsVersion="0x00020000"
android:required="true" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
+ tools:ignore="ScopedStorage" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
index a1ade722e8..740f3f48d3 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
@@ -30,10 +30,14 @@
package org.godotengine.editor
+import android.Manifest
import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Debug
+import android.os.Environment
+import android.widget.Toast
import androidx.window.layout.WindowMetricsCalculator
import org.godotengine.godot.FullScreenGodotApp
import org.godotengine.godot.utils.PermissionsUtil
@@ -68,7 +72,7 @@ open class GodotEditor : FullScreenGodotApp() {
val params = intent.getStringArrayExtra(COMMAND_LINE_PARAMS)
updateCommandLineParams(params)
- if (BuildConfig.BUILD_TYPE == "debug" && WAIT_FOR_DEBUGGER) {
+ if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) {
Debug.waitForDebugger()
}
@@ -143,4 +147,50 @@ open class GodotEditor : FullScreenGodotApp() {
* The Godot Android Editor sets its own orientation via its AndroidManifest
*/
protected open fun overrideOrientationRequest() = true
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ // Check if we got the MANAGE_EXTERNAL_STORAGE permission
+ if (requestCode == PermissionsUtil.REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ if (!Environment.isExternalStorageManager()) {
+ Toast.makeText(
+ this,
+ R.string.denied_storage_permission_error_msg,
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<String?>,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ // Check if we got access to the necessary storage permissions
+ if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ var hasReadAccess = false
+ var hasWriteAccess = false
+ for (i in permissions.indices) {
+ if (Manifest.permission.READ_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
+ hasReadAccess = true
+ }
+ if (Manifest.permission.WRITE_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) {
+ hasWriteAccess = true
+ }
+ }
+ if (!hasReadAccess || !hasWriteAccess) {
+ Toast.makeText(
+ this,
+ R.string.denied_storage_permission_error_msg,
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ }
+ }
+ }
}
diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml
index e8ce34f34d..837a5d62e1 100644
--- a/platform/android/java/editor/src/main/res/values/strings.xml
+++ b/platform/android/java/editor/src/main/res/values/strings.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="godot_editor_name_string">Godot Editor 4.x</string>
+
+ <string name="denied_storage_permission_error_msg">Missing storage access permission!</string>
</resources>
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index 228d8d45fa..79b5aadf2a 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -5,7 +5,7 @@
android:versionName="1.0">
<!-- Should match the mindSdk and targetSdk values in platform/android/java/app/config.gradle -->
- <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
+ <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="32" />
<application>
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index cafae94d62..28e689e63a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -34,6 +34,8 @@ import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.WINDOW_SERVICE;
import org.godotengine.godot.input.GodotEditText;
+import org.godotengine.godot.io.directory.DirectoryAccessHandler;
+import org.godotengine.godot.io.file.FileAccessHandler;
import org.godotengine.godot.plugin.GodotPlugin;
import org.godotengine.godot.plugin.GodotPluginRegistry;
import org.godotengine.godot.tts.GodotTTS;
@@ -164,9 +166,9 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
private Sensor mMagnetometer;
private Sensor mGyroscope;
- public static GodotIO io;
- public static GodotNetUtils netUtils;
- public static GodotTTS tts;
+ public GodotIO io;
+ public GodotNetUtils netUtils;
+ public GodotTTS tts;
public interface ResultCallback {
void callback(int requestCode, int resultCode, Intent data);
@@ -458,16 +460,26 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
final Activity activity = getActivity();
io = new GodotIO(activity);
- GodotLib.io = io;
netUtils = new GodotNetUtils(activity);
tts = new GodotTTS(activity);
+ Context context = getContext();
+ DirectoryAccessHandler directoryAccessHandler = new DirectoryAccessHandler(context);
+ FileAccessHandler fileAccessHandler = new FileAccessHandler(context);
mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
- GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion);
+ GodotLib.initialize(activity,
+ this,
+ activity.getAssets(),
+ io,
+ netUtils,
+ directoryAccessHandler,
+ fileAccessHandler,
+ use_apk_expansion,
+ tts);
result_callback = null;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index a8e3669ac6..0434efdf4c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -36,7 +36,6 @@ import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.res.AssetManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
@@ -46,12 +45,10 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.WindowInsets;
-import java.io.IOException;
import java.util.List;
import java.util.Locale;
@@ -60,7 +57,6 @@ import java.util.Locale;
public class GodotIO {
private static final String TAG = GodotIO.class.getSimpleName();
- private final AssetManager am;
private final Activity activity;
private final String uniqueId;
GodotEditText edit;
@@ -73,100 +69,8 @@ public class GodotIO {
final int SCREEN_SENSOR_PORTRAIT = 5;
final int SCREEN_SENSOR = 6;
- /////////////////////////
- /// DIRECTORIES
- /////////////////////////
-
- static class AssetDir {
- public String[] files;
- public int current;
- public String path;
- }
-
- private int last_dir_id = 1;
-
- private final SparseArray<AssetDir> dirs;
-
- public int dir_open(String path) {
- AssetDir ad = new AssetDir();
- ad.current = 0;
- ad.path = path;
-
- try {
- ad.files = am.list(path);
- // no way to find path is directory or file exactly.
- // but if ad.files.length==0, then it's an empty directory or file.
- if (ad.files.length == 0) {
- return -1;
- }
- } catch (IOException e) {
- System.out.printf("Exception on dir_open: %s\n", e);
- return -1;
- }
-
- ++last_dir_id;
- dirs.put(last_dir_id, ad);
-
- return last_dir_id;
- }
-
- public boolean dir_is_dir(int id) {
- if (dirs.get(id) == null) {
- System.out.printf("dir_next: invalid dir id: %d\n", id);
- return false;
- }
- AssetDir ad = dirs.get(id);
- //System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
- int idx = ad.current;
- if (idx > 0)
- idx--;
-
- if (idx >= ad.files.length)
- return false;
- String fname = ad.files[idx];
-
- try {
- if (ad.path.equals(""))
- am.open(fname);
- else
- am.open(ad.path + "/" + fname);
- return false;
- } catch (Exception e) {
- return true;
- }
- }
-
- public String dir_next(int id) {
- if (dirs.get(id) == null) {
- System.out.printf("dir_next: invalid dir id: %d\n", id);
- return "";
- }
-
- AssetDir ad = dirs.get(id);
- //System.out.printf("go next: %d,%d\n",ad.current,ad.files.length);
-
- if (ad.current >= ad.files.length) {
- ad.current++;
- return "";
- }
- String r = ad.files[ad.current];
- ad.current++;
- return r;
- }
-
- public void dir_close(int id) {
- if (dirs.get(id) == null) {
- System.out.printf("dir_close: invalid dir id: %d\n", id);
- return;
- }
-
- dirs.remove(id);
- }
-
GodotIO(Activity p_activity) {
- am = p_activity.getAssets();
activity = p_activity;
- dirs = new SparseArray<>();
String androidId = Settings.Secure.getString(activity.getContentResolver(),
Settings.Secure.ANDROID_ID);
if (androidId == null) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 3182ab0666..e2ae62d9cf 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -31,8 +31,13 @@
package org.godotengine.godot;
import org.godotengine.godot.gl.GodotRenderer;
+import org.godotengine.godot.io.directory.DirectoryAccessHandler;
+import org.godotengine.godot.io.file.FileAccessHandler;
+import org.godotengine.godot.tts.GodotTTS;
+import org.godotengine.godot.utils.GodotNetUtils;
import android.app.Activity;
+import android.content.res.AssetManager;
import android.hardware.SensorEvent;
import android.view.Surface;
@@ -42,8 +47,6 @@ import javax.microedition.khronos.opengles.GL10;
* Wrapper for native library
*/
public class GodotLib {
- public static GodotIO io;
-
static {
System.loadLibrary("godot_android");
}
@@ -51,7 +54,15 @@ public class GodotLib {
/**
* Invoked on the main thread to initialize Godot native layer.
*/
- public static native void initialize(Activity activity, Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
+ public static native void initialize(Activity activity,
+ Godot p_instance,
+ AssetManager p_asset_manager,
+ GodotIO godotIO,
+ GodotNetUtils netUtils,
+ DirectoryAccessHandler directoryAccessHandler,
+ FileAccessHandler fileAccessHandler,
+ boolean use_apk_expansion,
+ GodotTTS tts);
/**
* Invoked on the main thread to clean up Godot native layer.
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
new file mode 100644
index 0000000000..c7bd55b620
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
@@ -0,0 +1,114 @@
+/*************************************************************************/
+/* StorageScope.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io
+
+import android.content.Context
+import android.os.Build
+import android.os.Environment
+import java.io.File
+
+/**
+ * Represents the different storage scopes.
+ */
+internal enum class StorageScope {
+ /**
+ * Covers internal and external directories accessible to the app without restrictions.
+ */
+ APP,
+
+ /**
+ * Covers shared directories (from Android 10 and higher).
+ */
+ SHARED,
+
+ /**
+ * Everything else..
+ */
+ UNKNOWN;
+
+ companion object {
+ /**
+ * Determines which [StorageScope] the given path falls under.
+ */
+ fun getStorageScope(context: Context, path: String?): StorageScope {
+ if (path == null) {
+ return UNKNOWN
+ }
+
+ val pathFile = File(path)
+ if (!pathFile.isAbsolute) {
+ return UNKNOWN
+ }
+
+ val canonicalPathFile = pathFile.canonicalPath
+
+ val internalAppDir = context.filesDir.canonicalPath ?: return UNKNOWN
+ if (canonicalPathFile.startsWith(internalAppDir)) {
+ return APP
+ }
+
+ val internalCacheDir = context.cacheDir.canonicalPath ?: return UNKNOWN
+ if (canonicalPathFile.startsWith(internalCacheDir)) {
+ return APP
+ }
+
+ val externalAppDir = context.getExternalFilesDir(null)?.canonicalPath ?: return UNKNOWN
+ if (canonicalPathFile.startsWith(externalAppDir)) {
+ return APP
+ }
+
+ val sharedDir = Environment.getExternalStorageDirectory().canonicalPath ?: return UNKNOWN
+ if (canonicalPathFile.startsWith(sharedDir)) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ // Before R, apps had access to shared storage so long as they have the right
+ // permissions (and flag on Q).
+ return APP
+ }
+
+ // Post R, access is limited based on the target destination
+ // 'Downloads' and 'Documents' are still accessible
+ val downloadsSharedDir =
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath
+ ?: return SHARED
+ val documentsSharedDir =
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath
+ ?: return SHARED
+ if (canonicalPathFile.startsWith(downloadsSharedDir) || canonicalPathFile.startsWith(documentsSharedDir)) {
+ return APP
+ }
+
+ return SHARED
+ }
+
+ return UNKNOWN
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/directory/AssetsDirectoryAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/directory/AssetsDirectoryAccess.kt
new file mode 100644
index 0000000000..098b10ae36
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/AssetsDirectoryAccess.kt
@@ -0,0 +1,177 @@
+/*************************************************************************/
+/* AssetsDirectoryAccess.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.directory
+
+import android.content.Context
+import android.util.Log
+import android.util.SparseArray
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.Companion.INVALID_DIR_ID
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.Companion.STARTING_DIR_ID
+import java.io.File
+import java.io.IOException
+
+/**
+ * Handles directories access within the Android assets directory.
+ */
+internal class AssetsDirectoryAccess(context: Context) : DirectoryAccessHandler.DirectoryAccess {
+
+ companion object {
+ private val TAG = AssetsDirectoryAccess::class.java.simpleName
+ }
+
+ private data class AssetDir(val path: String, val files: Array<String>, var current: Int = 0)
+
+ private val assetManager = context.assets
+
+ private var lastDirId = STARTING_DIR_ID
+ private val dirs = SparseArray<AssetDir>()
+
+ private fun getAssetsPath(originalPath: String): String {
+ if (originalPath.startsWith(File.separatorChar)) {
+ return originalPath.substring(1)
+ }
+ return originalPath
+ }
+
+ override fun hasDirId(dirId: Int) = dirs.indexOfKey(dirId) >= 0
+
+ override fun dirOpen(path: String): Int {
+ val assetsPath = getAssetsPath(path) ?: return INVALID_DIR_ID
+ try {
+ val files = assetManager.list(assetsPath) ?: return INVALID_DIR_ID
+ // Empty directories don't get added to the 'assets' directory, so
+ // if ad.files.length > 0 ==> path is directory
+ // if ad.files.length == 0 ==> path is file
+ if (files.isEmpty()) {
+ return INVALID_DIR_ID
+ }
+
+ val ad = AssetDir(assetsPath, files)
+
+ dirs.put(++lastDirId, ad)
+ return lastDirId
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception on dirOpen", e)
+ return INVALID_DIR_ID
+ }
+ }
+
+ override fun dirExists(path: String): Boolean {
+ val assetsPath = getAssetsPath(path)
+ try {
+ val files = assetManager.list(assetsPath) ?: return false
+ // Empty directories don't get added to the 'assets' directory, so
+ // if ad.files.length > 0 ==> path is directory
+ // if ad.files.length == 0 ==> path is file
+ return files.isNotEmpty()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception on dirExists", e)
+ return false
+ }
+ }
+
+ override fun fileExists(path: String): Boolean {
+ val assetsPath = getAssetsPath(path) ?: return false
+ try {
+ val files = assetManager.list(assetsPath) ?: return false
+ // Empty directories don't get added to the 'assets' directory, so
+ // if ad.files.length > 0 ==> path is directory
+ // if ad.files.length == 0 ==> path is file
+ return files.isEmpty()
+ } catch (e: IOException) {
+ Log.e(TAG, "Exception on fileExists", e)
+ return false
+ }
+ }
+
+ override fun dirIsDir(dirId: Int): Boolean {
+ val ad: AssetDir = dirs[dirId]
+
+ var idx = ad.current
+ if (idx > 0) {
+ idx--
+ }
+
+ if (idx >= ad.files.size) {
+ return false
+ }
+
+ val fileName = ad.files[idx]
+ // List the contents of $fileName. If it's a file, it will be empty, otherwise it'll be a
+ // directory
+ val filePath = if (ad.path == "") fileName else "${ad.path}/${fileName}"
+ val fileContents = assetManager.list(filePath)
+ return (fileContents?.size?: 0) > 0
+ }
+
+ override fun isCurrentHidden(dirId: Int): Boolean {
+ val ad = dirs[dirId]
+
+ var idx = ad.current
+ if (idx > 0) {
+ idx--
+ }
+
+ if (idx >= ad.files.size) {
+ return false
+ }
+
+ val fileName = ad.files[idx]
+ return fileName.startsWith('.')
+ }
+
+ override fun dirNext(dirId: Int): String {
+ val ad: AssetDir = dirs[dirId]
+
+ if (ad.current >= ad.files.size) {
+ ad.current++
+ return ""
+ }
+
+ return ad.files[ad.current++]
+ }
+
+ override fun dirClose(dirId: Int) {
+ dirs.remove(dirId)
+ }
+
+ override fun getDriveCount() = 0
+
+ override fun getDrive(drive: Int) = ""
+
+ override fun makeDir(dir: String) = false
+
+ override fun getSpaceLeft() = 0L
+
+ override fun rename(from: String, to: String) = false
+
+ override fun remove(filename: String) = false
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/directory/DirectoryAccessHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/io/directory/DirectoryAccessHandler.kt
new file mode 100644
index 0000000000..fedcf4843f
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/DirectoryAccessHandler.kt
@@ -0,0 +1,224 @@
+/*************************************************************************/
+/* DirectoryAccessHandler.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.directory
+
+import android.content.Context
+import android.util.Log
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.AccessType.ACCESS_FILESYSTEM
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.AccessType.ACCESS_RESOURCES
+
+/**
+ * Handles files and directories access and manipulation for the Android platform
+ */
+class DirectoryAccessHandler(context: Context) {
+
+ companion object {
+ private val TAG = DirectoryAccessHandler::class.java.simpleName
+
+ internal const val INVALID_DIR_ID = -1
+ internal const val STARTING_DIR_ID = 1
+
+ private fun getAccessTypeFromNative(accessType: Int): AccessType? {
+ return when (accessType) {
+ ACCESS_RESOURCES.nativeValue -> ACCESS_RESOURCES
+ ACCESS_FILESYSTEM.nativeValue -> ACCESS_FILESYSTEM
+ else -> null
+ }
+ }
+ }
+
+ private enum class AccessType(val nativeValue: Int) {
+ ACCESS_RESOURCES(0), ACCESS_FILESYSTEM(2)
+ }
+
+ internal interface DirectoryAccess {
+ fun dirOpen(path: String): Int
+ fun dirNext(dirId: Int): String
+ fun dirClose(dirId: Int)
+ fun dirIsDir(dirId: Int): Boolean
+ fun dirExists(path: String): Boolean
+ fun fileExists(path: String): Boolean
+ fun hasDirId(dirId: Int): Boolean
+ fun isCurrentHidden(dirId: Int): Boolean
+ fun getDriveCount() : Int
+ fun getDrive(drive: Int): String
+ fun makeDir(dir: String): Boolean
+ fun getSpaceLeft(): Long
+ fun rename(from: String, to: String): Boolean
+ fun remove(filename: String): Boolean
+ }
+
+ private val assetsDirAccess = AssetsDirectoryAccess(context)
+ private val fileSystemDirAccess = FilesystemDirectoryAccess(context)
+
+ private fun hasDirId(accessType: AccessType, dirId: Int): Boolean {
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.hasDirId(dirId)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.hasDirId(dirId)
+ }
+ }
+
+ fun dirOpen(nativeAccessType: Int, path: String?): Int {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (path == null || accessType == null) {
+ return INVALID_DIR_ID
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.dirOpen(path)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.dirOpen(path)
+ }
+ }
+
+ fun dirNext(nativeAccessType: Int, dirId: Int): String {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (accessType == null || !hasDirId(accessType, dirId)) {
+ Log.w(TAG, "dirNext: Invalid dir id: $dirId")
+ return ""
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.dirNext(dirId)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.dirNext(dirId)
+ }
+ }
+
+ fun dirClose(nativeAccessType: Int, dirId: Int) {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (accessType == null || !hasDirId(accessType, dirId)) {
+ Log.w(TAG, "dirClose: Invalid dir id: $dirId")
+ return
+ }
+
+ when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.dirClose(dirId)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.dirClose(dirId)
+ }
+ }
+
+ fun dirIsDir(nativeAccessType: Int, dirId: Int): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (accessType == null || !hasDirId(accessType, dirId)) {
+ Log.w(TAG, "dirIsDir: Invalid dir id: $dirId")
+ return false
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.dirIsDir(dirId)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.dirIsDir(dirId)
+ }
+ }
+
+ fun isCurrentHidden(nativeAccessType: Int, dirId: Int): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (accessType == null || !hasDirId(accessType, dirId)) {
+ return false
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.isCurrentHidden(dirId)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.isCurrentHidden(dirId)
+ }
+ }
+
+ fun dirExists(nativeAccessType: Int, path: String?): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (path == null || accessType == null) {
+ return false
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.dirExists(path)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.dirExists(path)
+ }
+ }
+
+ fun fileExists(nativeAccessType: Int, path: String?): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType)
+ if (path == null || accessType == null) {
+ return false
+ }
+
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.fileExists(path)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.fileExists(path)
+ }
+ }
+
+ fun getDriveCount(nativeAccessType: Int): Int {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return 0
+ return when(accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.getDriveCount()
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.getDriveCount()
+ }
+ }
+
+ fun getDrive(nativeAccessType: Int, drive: Int): String {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return ""
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.getDrive(drive)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.getDrive(drive)
+ }
+ }
+
+ fun makeDir(nativeAccessType: Int, dir: String): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return false
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.makeDir(dir)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.makeDir(dir)
+ }
+ }
+
+ fun getSpaceLeft(nativeAccessType: Int): Long {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return 0L
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.getSpaceLeft()
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.getSpaceLeft()
+ }
+ }
+
+ fun rename(nativeAccessType: Int, from: String, to: String): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return false
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.rename(from, to)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.rename(from, to)
+ }
+ }
+
+ fun remove(nativeAccessType: Int, filename: String): Boolean {
+ val accessType = getAccessTypeFromNative(nativeAccessType) ?: return false
+ return when (accessType) {
+ ACCESS_RESOURCES -> assetsDirAccess.remove(filename)
+ ACCESS_FILESYSTEM -> fileSystemDirAccess.remove(filename)
+ }
+ }
+
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
new file mode 100644
index 0000000000..c3acf42568
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
@@ -0,0 +1,230 @@
+/*************************************************************************/
+/* FileSystemDirectoryAccess.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.directory
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.os.Build
+import android.os.storage.StorageManager
+import android.util.Log
+import android.util.SparseArray
+import org.godotengine.godot.io.StorageScope
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.Companion.INVALID_DIR_ID
+import org.godotengine.godot.io.directory.DirectoryAccessHandler.Companion.STARTING_DIR_ID
+import org.godotengine.godot.io.file.FileAccessHandler
+import java.io.File
+
+/**
+ * Handles directories access with the internal and external filesystem.
+ */
+internal class FilesystemDirectoryAccess(private val context: Context):
+ DirectoryAccessHandler.DirectoryAccess {
+
+ companion object {
+ private val TAG = FilesystemDirectoryAccess::class.java.simpleName
+ }
+
+ private data class DirData(val dirFile: File, val files: Array<File>, var current: Int = 0)
+
+ private val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
+ private var lastDirId = STARTING_DIR_ID
+ private val dirs = SparseArray<DirData>()
+
+ private fun inScope(path: String): Boolean {
+ // Directory access is available for shared storage on Android 11+
+ // On Android 10, access is also available as long as the `requestLegacyExternalStorage`
+ // tag is available.
+ return StorageScope.getStorageScope(context, path) != StorageScope.UNKNOWN
+ }
+
+ override fun hasDirId(dirId: Int) = dirs.indexOfKey(dirId) >= 0
+
+ override fun dirOpen(path: String): Int {
+ if (!inScope(path)) {
+ Log.w(TAG, "Path $path is not accessible.")
+ return INVALID_DIR_ID
+ }
+
+ // Check this is a directory.
+ val dirFile = File(path)
+ if (!dirFile.isDirectory) {
+ return INVALID_DIR_ID
+ }
+
+ // Get the files in the directory
+ val files = dirFile.listFiles()?: return INVALID_DIR_ID
+
+ // Create the data representing this directory
+ val dirData = DirData(dirFile, files)
+
+ dirs.put(++lastDirId, dirData)
+ return lastDirId
+ }
+
+ override fun dirExists(path: String): Boolean {
+ if (!inScope(path)) {
+ Log.w(TAG, "Path $path is not accessible.")
+ return false
+ }
+
+ try {
+ return File(path).isDirectory
+ } catch (e: SecurityException) {
+ return false
+ }
+ }
+
+ override fun fileExists(path: String) = FileAccessHandler.fileExists(context, path)
+
+ override fun dirNext(dirId: Int): String {
+ val dirData = dirs[dirId]
+ if (dirData.current >= dirData.files.size) {
+ dirData.current++
+ return ""
+ }
+
+ return dirData.files[dirData.current++].name
+ }
+
+ override fun dirClose(dirId: Int) {
+ dirs.remove(dirId)
+ }
+
+ override fun dirIsDir(dirId: Int): Boolean {
+ val dirData = dirs[dirId]
+
+ var index = dirData.current
+ if (index > 0) {
+ index--
+ }
+
+ if (index >= dirData.files.size) {
+ return false
+ }
+
+ return dirData.files[index].isDirectory
+ }
+
+ override fun isCurrentHidden(dirId: Int): Boolean {
+ val dirData = dirs[dirId]
+
+ var index = dirData.current
+ if (index > 0) {
+ index--
+ }
+
+ if (index >= dirData.files.size) {
+ return false
+ }
+
+ return dirData.files[index].isHidden
+ }
+
+ override fun getDriveCount(): Int {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ storageManager.storageVolumes.size
+ } else {
+ 0
+ }
+ }
+
+ override fun getDrive(drive: Int): String {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ return ""
+ }
+
+ if (drive < 0 || drive >= storageManager.storageVolumes.size) {
+ return ""
+ }
+
+ val storageVolume = storageManager.storageVolumes[drive]
+ return storageVolume.getDescription(context)
+ }
+
+ override fun makeDir(dir: String): Boolean {
+ if (!inScope(dir)) {
+ Log.w(TAG, "Directory $dir is not accessible.")
+ return false
+ }
+
+ try {
+ val dirFile = File(dir)
+ return dirFile.isDirectory || dirFile.mkdirs()
+ } catch (e: SecurityException) {
+ return false
+ }
+ }
+
+ @SuppressLint("UsableSpace")
+ override fun getSpaceLeft() = context.getExternalFilesDir(null)?.usableSpace ?: 0L
+
+ override fun rename(from: String, to: String): Boolean {
+ if (!inScope(from) || !inScope(to)) {
+ Log.w(TAG, "Argument filenames are not accessible:\n" +
+ "from: $from\n" +
+ "to: $to")
+ return false
+ }
+
+ return try {
+ val fromFile = File(from)
+ if (fromFile.isDirectory) {
+ fromFile.renameTo(File(to))
+ } else {
+ FileAccessHandler.renameFile(context, from, to)
+ }
+ } catch (e: SecurityException) {
+ false
+ }
+ }
+
+ override fun remove(filename: String): Boolean {
+ if (!inScope(filename)) {
+ Log.w(TAG, "Filename $filename is not accessible.")
+ return false
+ }
+
+ return try {
+ val deleteFile = File(filename)
+ if (deleteFile.exists()) {
+ if (deleteFile.isDirectory) {
+ deleteFile.delete()
+ } else {
+ FileAccessHandler.removeFile(context, filename)
+ }
+ } else {
+ true
+ }
+ } catch (e: SecurityException) {
+ false
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
new file mode 100644
index 0000000000..aef1bed8ce
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
@@ -0,0 +1,186 @@
+/*************************************************************************/
+/* DataAccess.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.file
+
+import android.content.Context
+import android.os.Build
+import android.util.Log
+import org.godotengine.godot.io.StorageScope
+import java.io.IOException
+import java.nio.ByteBuffer
+import java.nio.channels.FileChannel
+import kotlin.math.max
+
+/**
+ * Base class for file IO operations.
+ *
+ * Its derived instances provide concrete implementations to handle regular file access, as well
+ * as file access through the media store API on versions of Android were scoped storage is enabled.
+ */
+internal abstract class DataAccess(private val filePath: String) {
+
+ companion object {
+ private val TAG = DataAccess::class.java.simpleName
+
+ fun generateDataAccess(
+ storageScope: StorageScope,
+ context: Context,
+ filePath: String,
+ accessFlag: FileAccessFlags
+ ): DataAccess? {
+ return when (storageScope) {
+ StorageScope.APP -> FileData(filePath, accessFlag)
+
+ StorageScope.SHARED -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ MediaStoreData(context, filePath, accessFlag)
+ } else {
+ null
+ }
+
+ StorageScope.UNKNOWN -> null
+ }
+ }
+
+ fun fileExists(storageScope: StorageScope, context: Context, path: String): Boolean {
+ return when(storageScope) {
+ StorageScope.APP -> FileData.fileExists(path)
+ StorageScope.SHARED -> MediaStoreData.fileExists(context, path)
+ StorageScope.UNKNOWN -> false
+ }
+ }
+
+ fun fileLastModified(storageScope: StorageScope, context: Context, path: String): Long {
+ return when(storageScope) {
+ StorageScope.APP -> FileData.fileLastModified(path)
+ StorageScope.SHARED -> MediaStoreData.fileLastModified(context, path)
+ StorageScope.UNKNOWN -> 0L
+ }
+ }
+
+ fun removeFile(storageScope: StorageScope, context: Context, path: String): Boolean {
+ return when(storageScope) {
+ StorageScope.APP -> FileData.delete(path)
+ StorageScope.SHARED -> MediaStoreData.delete(context, path)
+ StorageScope.UNKNOWN -> false
+ }
+ }
+
+ fun renameFile(storageScope: StorageScope, context: Context, from: String, to: String): Boolean {
+ return when(storageScope) {
+ StorageScope.APP -> FileData.rename(from, to)
+ StorageScope.SHARED -> MediaStoreData.rename(context, from, to)
+ StorageScope.UNKNOWN -> false
+ }
+ }
+ }
+
+ protected abstract val fileChannel: FileChannel
+ internal var endOfFile = false
+ private set
+
+ fun close() {
+ try {
+ fileChannel.close()
+ } catch (e: IOException) {
+ Log.w(TAG, "Exception when closing file $filePath.", e)
+ }
+ }
+
+ fun flush() {
+ try {
+ fileChannel.force(false)
+ } catch (e: IOException) {
+ Log.w(TAG, "Exception when flushing file $filePath.", e)
+ }
+ }
+
+ fun seek(position: Long) {
+ try {
+ fileChannel.position(position)
+ if (position <= size()) {
+ endOfFile = false
+ }
+ } catch (e: Exception) {
+ Log.w(TAG, "Exception when seeking file $filePath.", e)
+ }
+ }
+
+ fun seekFromEnd(positionFromEnd: Long) {
+ val positionFromBeginning = max(0, size() - positionFromEnd)
+ seek(positionFromBeginning)
+ }
+
+ fun position(): Long {
+ return try {
+ fileChannel.position()
+ } catch (e: IOException) {
+ Log.w(
+ TAG,
+ "Exception when retrieving position for file $filePath.",
+ e
+ )
+ 0L
+ }
+ }
+
+ fun size() = try {
+ fileChannel.size()
+ } catch (e: IOException) {
+ Log.w(TAG, "Exception when retrieving size for file $filePath.", e)
+ 0L
+ }
+
+ fun read(buffer: ByteBuffer): Int {
+ return try {
+ val readBytes = fileChannel.read(buffer)
+ if (readBytes == -1) {
+ endOfFile = true
+ 0
+ } else {
+ readBytes
+ }
+ } catch (e: IOException) {
+ Log.w(TAG, "Exception while reading from file $filePath.", e)
+ 0
+ }
+ }
+
+ fun write(buffer: ByteBuffer) {
+ try {
+ val writtenBytes = fileChannel.write(buffer)
+ if (writtenBytes > 0) {
+ endOfFile = false
+ }
+ } catch (e: IOException) {
+ Log.w(TAG, "Exception while writing to file $filePath.", e)
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt
new file mode 100644
index 0000000000..c6b242a4b6
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessFlags.kt
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* FileAccessFlags.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.file
+
+/**
+ * Android representation of Godot native access flags.
+ */
+internal enum class FileAccessFlags(val nativeValue: Int) {
+ /**
+ * Opens the file for read operations.
+ * The cursor is positioned at the beginning of the file.
+ */
+ READ(1),
+
+ /**
+ * Opens the file for write operations.
+ * The file is created if it does not exist, and truncated if it does.
+ */
+ WRITE(2),
+
+ /**
+ * Opens the file for read and write operations.
+ * Does not truncate the file. The cursor is positioned at the beginning of the file.
+ */
+ READ_WRITE(3),
+
+ /**
+ * Opens the file for read and write operations.
+ * The file is created if it does not exist, and truncated if it does.
+ * The cursor is positioned at the beginning of the file.
+ */
+ WRITE_READ(7);
+
+ fun getMode(): String {
+ return when (this) {
+ READ -> "r"
+ WRITE -> "w"
+ READ_WRITE, WRITE_READ -> "rw"
+ }
+ }
+
+ fun shouldTruncate(): Boolean {
+ return when (this) {
+ READ, READ_WRITE -> false
+ WRITE, WRITE_READ -> true
+ }
+ }
+
+ companion object {
+ fun fromNativeModeFlags(modeFlag: Int): FileAccessFlags? {
+ for (flag in values()) {
+ if (flag.nativeValue == modeFlag) {
+ return flag
+ }
+ }
+ return null
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
new file mode 100644
index 0000000000..a4e0a82d6e
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
@@ -0,0 +1,202 @@
+/*************************************************************************/
+/* FileAccessHandler.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.file
+
+import android.content.Context
+import android.util.Log
+import android.util.SparseArray
+import org.godotengine.godot.io.StorageScope
+import java.io.FileNotFoundException
+import java.nio.ByteBuffer
+
+/**
+ * Handles regular and media store file access and interactions.
+ */
+class FileAccessHandler(val context: Context) {
+
+ companion object {
+ private val TAG = FileAccessHandler::class.java.simpleName
+
+ private const val FILE_NOT_FOUND_ERROR_ID = -1
+ private const val INVALID_FILE_ID = 0
+ private const val STARTING_FILE_ID = 1
+
+ fun fileExists(context: Context, path: String?): Boolean {
+ val storageScope = StorageScope.getStorageScope(context, path)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.fileExists(storageScope, context, path!!)
+ } catch (e: SecurityException) {
+ false
+ }
+ }
+
+ fun removeFile(context: Context, path: String?): Boolean {
+ val storageScope = StorageScope.getStorageScope(context, path)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.removeFile(storageScope, context, path!!)
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+ fun renameFile(context: Context, from: String?, to: String?): Boolean {
+ val storageScope = StorageScope.getStorageScope(context, from)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return false
+ }
+
+ return try {
+ DataAccess.renameFile(storageScope, context, from!!, to!!)
+ } catch (e: Exception) {
+ false
+ }
+ }
+ }
+
+ private val files = SparseArray<DataAccess>()
+ private var lastFileId = STARTING_FILE_ID
+
+ private fun hasFileId(fileId: Int) = files.indexOfKey(fileId) >= 0
+
+ fun fileOpen(path: String?, modeFlags: Int): Int {
+ val storageScope = StorageScope.getStorageScope(context, path)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return INVALID_FILE_ID
+ }
+
+ try {
+ val accessFlag = FileAccessFlags.fromNativeModeFlags(modeFlags) ?: return INVALID_FILE_ID
+ val dataAccess = DataAccess.generateDataAccess(storageScope, context, path!!, accessFlag) ?: return INVALID_FILE_ID
+
+ files.put(++lastFileId, dataAccess)
+ return lastFileId
+ } catch (e: FileNotFoundException) {
+ return FILE_NOT_FOUND_ERROR_ID
+ } catch (e: Exception) {
+ Log.w(TAG, "Error while opening $path", e)
+ return INVALID_FILE_ID
+ }
+ }
+
+ fun fileGetSize(fileId: Int): Long {
+ if (!hasFileId(fileId)) {
+ return 0L
+ }
+
+ return files[fileId].size()
+ }
+
+ fun fileSeek(fileId: Int, position: Long) {
+ if (!hasFileId(fileId)) {
+ return
+ }
+
+ files[fileId].seek(position)
+ }
+
+ fun fileSeekFromEnd(fileId: Int, position: Long) {
+ if (!hasFileId(fileId)) {
+ return
+ }
+
+ files[fileId].seekFromEnd(position)
+ }
+
+ fun fileRead(fileId: Int, byteBuffer: ByteBuffer?): Int {
+ if (!hasFileId(fileId) || byteBuffer == null) {
+ return 0
+ }
+
+ return files[fileId].read(byteBuffer)
+ }
+
+ fun fileWrite(fileId: Int, byteBuffer: ByteBuffer?) {
+ if (!hasFileId(fileId) || byteBuffer == null) {
+ return
+ }
+
+ files[fileId].write(byteBuffer)
+ }
+
+ fun fileFlush(fileId: Int) {
+ if (!hasFileId(fileId)) {
+ return
+ }
+
+ files[fileId].flush()
+ }
+
+ fun fileExists(path: String?) = Companion.fileExists(context, path)
+
+ fun fileLastModified(filepath: String?): Long {
+ val storageScope = StorageScope.getStorageScope(context, filepath)
+ if (storageScope == StorageScope.UNKNOWN) {
+ return 0L
+ }
+
+ return try {
+ DataAccess.fileLastModified(storageScope, context, filepath!!)
+ } catch (e: SecurityException) {
+ 0L
+ }
+ }
+
+ fun fileGetPosition(fileId: Int): Long {
+ if (!hasFileId(fileId)) {
+ return 0L
+ }
+
+ return files[fileId].position()
+ }
+
+ fun isFileEof(fileId: Int): Boolean {
+ if (!hasFileId(fileId)) {
+ return false
+ }
+
+ return files[fileId].endOfFile
+ }
+
+ fun fileClose(fileId: Int) {
+ if (hasFileId(fileId)) {
+ files[fileId].close()
+ files.remove(fileId)
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt
new file mode 100644
index 0000000000..5af694ad99
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileData.kt
@@ -0,0 +1,93 @@
+/*************************************************************************/
+/* FileData.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.file
+
+import java.io.File
+import java.io.FileOutputStream
+import java.io.RandomAccessFile
+import java.nio.channels.FileChannel
+
+/**
+ * Implementation of [DataAccess] which handles regular (not scoped) file access and interactions.
+ */
+internal class FileData(filePath: String, accessFlag: FileAccessFlags) : DataAccess(filePath) {
+
+ companion object {
+ private val TAG = FileData::class.java.simpleName
+
+ fun fileExists(path: String): Boolean {
+ return try {
+ File(path).isFile
+ } catch (e: SecurityException) {
+ false
+ }
+ }
+
+ fun fileLastModified(filepath: String): Long {
+ return try {
+ File(filepath).lastModified()
+ } catch (e: SecurityException) {
+ 0L
+ }
+ }
+
+ fun delete(filepath: String): Boolean {
+ return try {
+ File(filepath).delete()
+ } catch (e: Exception) {
+ false
+ }
+ }
+
+ fun rename(from: String, to: String): Boolean {
+ return try {
+ val fromFile = File(from)
+ fromFile.renameTo(File(to))
+ } catch (e: Exception) {
+ false
+ }
+ }
+ }
+
+ override val fileChannel: FileChannel
+
+ init {
+ if (accessFlag == FileAccessFlags.WRITE) {
+ fileChannel = FileOutputStream(filePath, !accessFlag.shouldTruncate()).channel
+ } else {
+ fileChannel = RandomAccessFile(filePath, accessFlag.getMode()).channel
+ }
+
+ if (accessFlag.shouldTruncate()) {
+ fileChannel.truncate(0)
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt
new file mode 100644
index 0000000000..81a7dd1705
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/MediaStoreData.kt
@@ -0,0 +1,284 @@
+/*************************************************************************/
+/* MediaStoreData.kt */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.io.file
+
+import android.content.ContentUris
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import android.net.Uri
+import android.os.Build
+import android.os.Environment
+import android.provider.MediaStore
+import androidx.annotation.RequiresApi
+
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.nio.channels.FileChannel
+
+/**
+ * Implementation of [DataAccess] which handles access and interactions with file and data
+ * under scoped storage via the MediaStore API.
+ */
+@RequiresApi(Build.VERSION_CODES.Q)
+internal class MediaStoreData(context: Context, filePath: String, accessFlag: FileAccessFlags) :
+ DataAccess(filePath) {
+
+ private data class DataItem(
+ val id: Long,
+ val uri: Uri,
+ val displayName: String,
+ val relativePath: String,
+ val size: Int,
+ val dateModified: Int,
+ val mediaType: Int
+ )
+
+ companion object {
+ private val TAG = MediaStoreData::class.java.simpleName
+
+ private val COLLECTION = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
+
+ private val PROJECTION = arrayOf(
+ MediaStore.Files.FileColumns._ID,
+ MediaStore.Files.FileColumns.DISPLAY_NAME,
+ MediaStore.Files.FileColumns.RELATIVE_PATH,
+ MediaStore.Files.FileColumns.SIZE,
+ MediaStore.Files.FileColumns.DATE_MODIFIED,
+ MediaStore.Files.FileColumns.MEDIA_TYPE,
+ )
+
+ private const val SELECTION_BY_PATH = "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ? " +
+ " AND ${MediaStore.Files.FileColumns.RELATIVE_PATH} = ?"
+
+ private fun getSelectionByPathArguments(path: String): Array<String> {
+ return arrayOf(getMediaStoreDisplayName(path), getMediaStoreRelativePath(path))
+ }
+
+ private const val SELECTION_BY_ID = "${MediaStore.Files.FileColumns._ID} = ? "
+
+ private fun getSelectionByIdArgument(id: Long) = arrayOf(id.toString())
+
+ private fun getMediaStoreDisplayName(path: String) = File(path).name
+
+ private fun getMediaStoreRelativePath(path: String): String {
+ val pathFile = File(path)
+ val environmentDir = Environment.getExternalStorageDirectory()
+ var relativePath = (pathFile.parent?.replace(environmentDir.absolutePath, "") ?: "").trim('/')
+ if (relativePath.isNotBlank()) {
+ relativePath += "/"
+ }
+ return relativePath
+ }
+
+ private fun queryById(context: Context, id: Long): List<DataItem> {
+ val query = context.contentResolver.query(
+ COLLECTION,
+ PROJECTION,
+ SELECTION_BY_ID,
+ getSelectionByIdArgument(id),
+ null
+ )
+ return dataItemFromCursor(query)
+ }
+
+ private fun queryByPath(context: Context, path: String): List<DataItem> {
+ val query = context.contentResolver.query(
+ COLLECTION,
+ PROJECTION,
+ SELECTION_BY_PATH,
+ getSelectionByPathArguments(path),
+ null
+ )
+ return dataItemFromCursor(query)
+ }
+
+ private fun dataItemFromCursor(query: Cursor?): List<DataItem> {
+ query?.use { cursor ->
+ cursor.count
+ if (cursor.count == 0) {
+ return emptyList()
+ }
+ val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
+ val displayNameColumn =
+ cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)
+ val relativePathColumn =
+ cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.RELATIVE_PATH)
+ val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE)
+ val dateModifiedColumn =
+ cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATE_MODIFIED)
+ val mediaTypeColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MEDIA_TYPE)
+
+ val result = ArrayList<DataItem>()
+ while (cursor.moveToNext()) {
+ val id = cursor.getLong(idColumn)
+ result.add(
+ DataItem(
+ id,
+ ContentUris.withAppendedId(COLLECTION, id),
+ cursor.getString(displayNameColumn),
+ cursor.getString(relativePathColumn),
+ cursor.getInt(sizeColumn),
+ cursor.getInt(dateModifiedColumn),
+ cursor.getInt(mediaTypeColumn)
+ )
+ )
+ }
+ return result
+ }
+ return emptyList()
+ }
+
+ private fun addFile(context: Context, path: String): DataItem? {
+ val fileDetails = ContentValues().apply {
+ put(MediaStore.Files.FileColumns._ID, 0)
+ put(MediaStore.Files.FileColumns.DISPLAY_NAME, getMediaStoreDisplayName(path))
+ put(MediaStore.Files.FileColumns.RELATIVE_PATH, getMediaStoreRelativePath(path))
+ }
+
+ context.contentResolver.insert(COLLECTION, fileDetails) ?: return null
+
+ // File was successfully added, let's retrieve its info
+ val infos = queryByPath(context, path)
+ if (infos.isEmpty()) {
+ return null
+ }
+
+ return infos[0]
+ }
+
+ fun delete(context: Context, path: String): Boolean {
+ val itemsToDelete = queryByPath(context, path)
+ if (itemsToDelete.isEmpty()) {
+ return false
+ }
+
+ val resolver = context.contentResolver
+ var itemsDeleted = 0
+ for (item in itemsToDelete) {
+ itemsDeleted += resolver.delete(item.uri, null, null)
+ }
+
+ return itemsDeleted > 0
+ }
+
+ fun fileExists(context: Context, path: String): Boolean {
+ return queryByPath(context, path).isNotEmpty()
+ }
+
+ fun fileLastModified(context: Context, path: String): Long {
+ val result = queryByPath(context, path)
+ if (result.isEmpty()) {
+ return 0L
+ }
+
+ val dataItem = result[0]
+ return dataItem.dateModified.toLong()
+ }
+
+ fun rename(context: Context, from: String, to: String): Boolean {
+ // Ensure the source exists.
+ val sources = queryByPath(context, from)
+ if (sources.isEmpty()) {
+ return false
+ }
+
+ // Take the first source
+ val source = sources[0]
+
+ // Set up the updated values
+ val updatedDetails = ContentValues().apply {
+ put(MediaStore.Files.FileColumns.DISPLAY_NAME, getMediaStoreDisplayName(to))
+ put(MediaStore.Files.FileColumns.RELATIVE_PATH, getMediaStoreRelativePath(to))
+ }
+
+ val updated = context.contentResolver.update(
+ source.uri,
+ updatedDetails,
+ SELECTION_BY_ID,
+ getSelectionByIdArgument(source.id)
+ )
+ return updated > 0
+ }
+ }
+
+ private val id: Long
+ private val uri: Uri
+ override val fileChannel: FileChannel
+
+ init {
+ val contentResolver = context.contentResolver
+ val dataItems = queryByPath(context, filePath)
+
+ val dataItem = when (accessFlag) {
+ FileAccessFlags.READ -> {
+ // The file should already exist
+ if (dataItems.isEmpty()) {
+ throw FileNotFoundException("Unable to access file $filePath")
+ }
+
+ val dataItem = dataItems[0]
+ dataItem
+ }
+
+ FileAccessFlags.WRITE, FileAccessFlags.READ_WRITE, FileAccessFlags.WRITE_READ -> {
+ // Create the file if it doesn't exist
+ val dataItem = if (dataItems.isEmpty()) {
+ addFile(context, filePath)
+ } else {
+ dataItems[0]
+ }
+
+ if (dataItem == null) {
+ throw FileNotFoundException("Unable to access file $filePath")
+ }
+ dataItem
+ }
+ }
+
+ id = dataItem.id
+ uri = dataItem.uri
+
+ val parcelFileDescriptor = contentResolver.openFileDescriptor(uri, accessFlag.getMode())
+ ?: throw IllegalStateException("Unable to access file descriptor")
+ fileChannel = if (accessFlag == FileAccessFlags.READ) {
+ FileInputStream(parcelFileDescriptor.fileDescriptor).channel
+ } else {
+ FileOutputStream(parcelFileDescriptor.fileDescriptor).channel
+ }
+
+ if (accessFlag.shouldTruncate()) {
+ fileChannel.truncate(0)
+ }
+ }
+}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index e5b4f41153..57db0709f0 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -32,10 +32,14 @@ package org.godotengine.godot.utils;
import android.Manifest;
import android.app.Activity;
+import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
+import android.net.Uri;
import android.os.Build;
+import android.os.Environment;
+import android.provider.Settings;
import android.util.Log;
import androidx.core.content.ContextCompat;
@@ -53,7 +57,8 @@ public final class PermissionsUtil {
static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
static final int REQUEST_CAMERA_PERMISSION = 2;
static final int REQUEST_VIBRATE_PERMISSION = 3;
- static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001;
+ public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001;
+ public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002;
private PermissionsUtil() {
}
@@ -108,13 +113,26 @@ public final class PermissionsUtil {
if (manifestPermissions.length == 0)
return true;
- List<String> dangerousPermissions = new ArrayList<>();
+ List<String> requestedPermissions = new ArrayList<>();
for (String manifestPermission : manifestPermissions) {
try {
- PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission);
- int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
- if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) != PackageManager.PERMISSION_GRANTED) {
- dangerousPermissions.add(manifestPermission);
+ if (manifestPermission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
+ try {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
+ intent.setData(Uri.parse(String.format("package:%s", activity.getPackageName())));
+ activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE);
+ } catch (Exception ignored) {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
+ activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE);
+ }
+ }
+ } else {
+ PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission);
+ int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
+ if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) != PackageManager.PERMISSION_GRANTED) {
+ requestedPermissions.add(manifestPermission);
+ }
}
} catch (PackageManager.NameNotFoundException e) {
// Skip this permission and continue.
@@ -122,13 +140,12 @@ public final class PermissionsUtil {
}
}
- if (dangerousPermissions.isEmpty()) {
+ if (requestedPermissions.isEmpty()) {
// If list is empty, all of dangerous permissions were granted.
return true;
}
- String[] requestedPermissions = dangerousPermissions.toArray(new String[0]);
- activity.requestPermissions(requestedPermissions, REQUEST_ALL_PERMISSION_REQ_CODE);
+ activity.requestPermissions(requestedPermissions.toArray(new String[0]), REQUEST_ALL_PERMISSION_REQ_CODE);
return false;
}
@@ -148,13 +165,19 @@ public final class PermissionsUtil {
if (manifestPermissions.length == 0)
return manifestPermissions;
- List<String> dangerousPermissions = new ArrayList<>();
+ List<String> grantedPermissions = new ArrayList<>();
for (String manifestPermission : manifestPermissions) {
try {
- PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission);
- int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
- if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
- dangerousPermissions.add(manifestPermission);
+ if (manifestPermission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && Environment.isExternalStorageManager()) {
+ grantedPermissions.add(manifestPermission);
+ }
+ } else {
+ PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission);
+ int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
+ if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
+ grantedPermissions.add(manifestPermission);
+ }
}
} catch (PackageManager.NameNotFoundException e) {
// Skip this permission and continue.
@@ -162,7 +185,7 @@ public final class PermissionsUtil {
}
}
- return dangerousPermissions.toArray(new String[0]);
+ return grantedPermissions.toArray(new String[0]);
}
/**
@@ -177,7 +200,7 @@ public final class PermissionsUtil {
if (permission.equals(p))
return true;
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (PackageManager.NameNotFoundException ignored) {
}
return false;
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index eaffe14b13..f4de4acfad 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -43,6 +43,7 @@
#include "dir_access_jandroid.h"
#include "display_server_android.h"
#include "file_access_android.h"
+#include "file_access_filesystem_jandroid.h"
#include "jni_utils.h"
#include "main/main.h"
#include "net_socket_android.h"
@@ -78,13 +79,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei
}
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts) {
JavaVM *jvm;
env->GetJavaVM(&jvm);
// create our wrapper classes
- godot_java = new GodotJavaWrapper(env, activity, godot_instance);
- godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
+ godot_java = new GodotJavaWrapper(env, p_activity, p_godot_instance);
+ godot_io_java = new GodotIOJavaWrapper(env, p_godot_io);
init_thread_jandroid(jvm, env);
@@ -92,9 +93,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
FileAccessAndroid::asset_manager = AAssetManager_fromJava(env, amgr);
- DirAccessJAndroid::setup(godot_io_java->get_instance());
- NetSocketAndroid::setup(godot_java->get_member_object("netUtils", "Lorg/godotengine/godot/utils/GodotNetUtils;", env));
- TTS_Android::setup(godot_java->get_member_object("tts", "Lorg/godotengine/godot/tts/GodotTTS;", env));
+ DirAccessJAndroid::setup(p_directory_access_handler);
+ FileAccessFilesystemJAndroid::setup(p_file_access_handler);
+ NetSocketAndroid::setup(p_net_utils);
+ TTS_Android::setup(p_godot_tts);
os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion);
@@ -157,6 +159,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
memfree(cmdline);
}
+ // Note: --help and --version return ERR_HELP, but this should be translated to 0 if exit codes are propagated.
if (err != OK) {
return; // should exit instead and print the error
}
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index aa8d67cf46..de16f197b8 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -37,7 +37,7 @@
// These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code.
// See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names)
extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 6674428de8..0f551e7f4f 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -40,6 +40,7 @@
#include "dir_access_jandroid.h"
#include "file_access_android.h"
+#include "file_access_filesystem_jandroid.h"
#include "net_socket_android.h"
#include <dlfcn.h>
@@ -93,7 +94,7 @@ void OS_Android::initialize_core() {
}
#endif
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
- FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
+ FileAccess::make_default<FileAccessFilesystemJAndroid>(FileAccess::ACCESS_FILESYSTEM);
#ifdef TOOLS_ENABLED
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
@@ -105,7 +106,7 @@ void OS_Android::initialize_core() {
}
#endif
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
- DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
+ DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_FILESYSTEM);
NetSocketAndroid::make_default();
}
@@ -300,6 +301,33 @@ String OS_Android::get_system_dir(SystemDir p_dir, bool p_shared_storage) const
return godot_io_java->get_system_dir(p_dir, p_shared_storage);
}
+Error OS_Android::move_to_trash(const String &p_path) {
+ Ref<DirAccess> da_ref = DirAccess::create_for_path(p_path);
+ if (da_ref.is_null()) {
+ return FAILED;
+ }
+
+ // Check if it's a directory
+ if (da_ref->dir_exists(p_path)) {
+ Error err = da_ref->change_dir(p_path);
+ if (err) {
+ return err;
+ }
+ // This is directory, let's erase its contents
+ err = da_ref->erase_contents_recursive();
+ if (err) {
+ return err;
+ }
+ // Remove the top directory
+ return da_ref->remove(p_path);
+ } else if (da_ref->file_exists(p_path)) {
+ // This is a file, let's remove it.
+ return da_ref->remove(p_path);
+ } else {
+ return FAILED;
+ }
+}
+
void OS_Android::set_display_size(const Size2i &p_size) {
display_size = p_size;
}
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 3f607eac48..96c06d715c 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -122,6 +122,8 @@ public:
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
+ virtual Error move_to_trash(const String &p_path) override;
+
void vibrate_handheld(int p_duration_ms) override;
virtual String get_config_path() const override;
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 392a0151be..862f1fe50b 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -98,10 +98,12 @@ def configure(env):
if env["ios_simulator"]:
detect_darwin_sdk_path("iphonesimulator", env)
+ env.Append(ASFLAGS=["-mios-simulator-version-min=13.0"])
env.Append(CCFLAGS=["-mios-simulator-version-min=13.0"])
env.extra_suffix = ".simulator" + env.extra_suffix
else:
detect_darwin_sdk_path("iphone", env)
+ env.Append(ASFLAGS=["-miphoneos-version-min=11.0"])
env.Append(CCFLAGS=["-miphoneos-version-min=11.0"])
if env["arch"] == "x86_64":
@@ -113,6 +115,7 @@ def configure(env):
" -fasm-blocks -isysroot $IPHONESDK"
).split()
)
+ env.Append(ASFLAGS=["-arch", "x86_64"])
elif env["arch"] == "arm64":
env.Append(
CCFLAGS=(
@@ -122,6 +125,7 @@ def configure(env):
" -isysroot $IPHONESDK".split()
)
)
+ env.Append(ASFLAGS=["-arch", "arm64"])
env.Append(CPPDEFINES=["NEED_LONG_INT"])
# Disable exceptions on non-tools (template) builds
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index 573ee9b7a8..28ffc9595e 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -195,6 +195,7 @@ void DisplayServerIPhone::window_set_drop_files_callback(const Callable &p_calla
}
void DisplayServerIPhone::process_events() {
+ Input::get_singleton()->flush_buffered_events();
}
void DisplayServerIPhone::_dispatch_input_events(const Ref<InputEvent> &p_event) {
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index 4cf1c279eb..3b92bd19be 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -1838,12 +1838,8 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
}
EditorExportPlatformIOS::EditorExportPlatformIOS() {
- Ref<Image> img = memnew(Image(_iphone_logo));
- logo.instantiate();
- logo->create_from_image(img);
-
+ logo = ImageTexture::create_from_image(memnew(Image(_iphone_logo)));
plugins_changed.set();
-
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
diff --git a/platform/iphone/godot_iphone.mm b/platform/iphone/godot_iphone.mm
index 49474ef554..59fdfa9dcd 100644
--- a/platform/iphone/godot_iphone.mm
+++ b/platform/iphone/godot_iphone.mm
@@ -112,7 +112,10 @@ int iphone_main(int argc, char **argv, String data_dir, String cache_dir) {
Error err = Main::setup(fargv[0], argc - 1, &fargv[1], false);
printf("setup %i\n", err);
- if (err != OK) {
+
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return 0;
+ } else if (err != OK) {
return 255;
}
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index a96c539a1f..4edd6c793a 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -236,7 +236,7 @@ void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double
const char *DisplayServerJavaScript::godot2dom_cursor(DisplayServer::CursorShape p_shape) {
switch (p_shape) {
case DisplayServer::CURSOR_ARROW:
- return "auto";
+ return "default";
case DisplayServer::CURSOR_IBEAM:
return "text";
case DisplayServer::CURSOR_POINTING_HAND:
@@ -270,7 +270,7 @@ const char *DisplayServerJavaScript::godot2dom_cursor(DisplayServer::CursorShape
case DisplayServer::CURSOR_HELP:
return "help";
default:
- return "auto";
+ return "default";
}
}
diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp
index 901580c140..e2ae45627e 100644
--- a/platform/javascript/export/export_plugin.cpp
+++ b/platform/javascript/export/export_plugin.cpp
@@ -661,13 +661,8 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
server.instantiate();
server_thread.start(_server_thread_poll, this);
- Ref<Image> img = memnew(Image(_javascript_logo));
- logo.instantiate();
- logo->create_from_image(img);
-
- img = Ref<Image>(memnew(Image(_javascript_run_icon)));
- run_icon.instantiate();
- run_icon->create_from_image(img);
+ logo = ImageTexture::create_from_image(memnew(Image(_javascript_logo)));
+ run_icon = ImageTexture::create_from_image(memnew(Image(_javascript_run_icon)));
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
if (theme.is_valid()) {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 4aec111022..b0f87484b9 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -196,6 +196,7 @@ bool DisplayServerX11::_refresh_device_info() {
xi.absolute_devices.clear();
xi.touch_devices.clear();
+ xi.pen_inverted_devices.clear();
int dev_count;
XIDeviceInfo *info = XIQueryDevice(x11_display, XIAllDevices, &dev_count);
@@ -205,7 +206,7 @@ bool DisplayServerX11::_refresh_device_info() {
if (!dev->enabled) {
continue;
}
- if (!(dev->use == XIMasterPointer || dev->use == XIFloatingSlave)) {
+ if (!(dev->use == XISlavePointer || dev->use == XIFloatingSlave)) {
continue;
}
@@ -274,6 +275,7 @@ bool DisplayServerX11::_refresh_device_info() {
xi.pen_pressure_range[dev->deviceid] = Vector2(pressure_min, pressure_max);
xi.pen_tilt_x_range[dev->deviceid] = Vector2(tilt_x_min, tilt_x_max);
xi.pen_tilt_y_range[dev->deviceid] = Vector2(tilt_y_min, tilt_y_max);
+ xi.pen_inverted_devices[dev->deviceid] = (bool)strstr(dev->name, "eraser");
}
XIFreeDeviceInfo(info);
@@ -1817,6 +1819,52 @@ bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_a
return retval;
}
+bool DisplayServerX11::_window_fullscreen_check(WindowID p_window) const {
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
+
+ // Using EWMH -- Extended Window Manager Hints
+ Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom type;
+ int format;
+ unsigned long len;
+ unsigned long remaining;
+ unsigned char *data = nullptr;
+ bool retval = false;
+
+ if (property == None) {
+ return retval;
+ }
+
+ int result = XGetWindowProperty(
+ x11_display,
+ wd.x11_window,
+ property,
+ 0,
+ 1024,
+ False,
+ XA_ATOM,
+ &type,
+ &format,
+ &len,
+ &remaining,
+ &data);
+
+ if (result == Success) {
+ Atom *atoms = (Atom *)data;
+ Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False);
+ for (uint64_t i = 0; i < len; i++) {
+ if (atoms[i] == wm_fullscreen) {
+ retval = true;
+ break;
+ }
+ }
+ XFree(data);
+ }
+
+ return retval;
+}
+
bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const {
_THREAD_SAFE_METHOD_
return _window_maximize_check(p_window, "_NET_WM_ALLOWED_ACTIONS");
@@ -3438,7 +3486,7 @@ void DisplayServerX11::process_events() {
} break;
case XI_RawMotion: {
XIRawEvent *raw_event = (XIRawEvent *)event_data;
- int device_id = raw_event->deviceid;
+ int device_id = raw_event->sourceid;
// Determine the axis used (called valuators in XInput for some forsaken reason)
// Mask is a bitmask indicating which axes are involved.
@@ -3504,6 +3552,11 @@ void DisplayServerX11::process_events() {
values++;
}
+ HashMap<int, bool>::Iterator pen_inverted = xi.pen_inverted_devices.find(device_id);
+ if (pen_inverted) {
+ xi.pen_inverted = pen_inverted->value;
+ }
+
// https://bugs.freedesktop.org/show_bug.cgi?id=71609
// http://lists.libsdl.org/pipermail/commits-libsdl.org/2015-June/000282.html
if (raw_event->time == xi.last_relative_time && rel_x == xi.relative_motion.x && rel_y == xi.relative_motion.y) {
@@ -3604,6 +3657,8 @@ void DisplayServerX11::process_events() {
case Expose: {
DEBUG_LOG_X11("[%u] Expose window=%lu (%u), count='%u' \n", frame, event.xexpose.window, window_id, event.xexpose.count);
+ windows[window_id].fullscreen = _window_fullscreen_check(window_id);
+
Main::force_redraw();
} break;
@@ -3936,6 +3991,7 @@ void DisplayServerX11::process_events() {
mm->set_pressure(bool(mouse_get_button_state() & MouseButton::MASK_LEFT) ? 1.0f : 0.0f);
}
mm->set_tilt(xi.tilt);
+ mm->set_pen_inverted(xi.pen_inverted);
_get_key_modifier_state(event.xmotion.state, mm);
mm->set_button_mask((MouseButton)mouse_get_button_state());
@@ -4119,13 +4175,17 @@ void DisplayServerX11::process_events() {
void DisplayServerX11::release_rendering_thread() {
#if defined(GLES3_ENABLED)
- gl_manager->release_current();
+ if (gl_manager) {
+ gl_manager->release_current();
+ }
#endif
}
void DisplayServerX11::make_rendering_thread() {
#if defined(GLES3_ENABLED)
- gl_manager->make_current();
+ if (gl_manager) {
+ gl_manager->make_current();
+ }
#endif
}
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 4beeddd3a8..9ce6a557db 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -201,10 +201,12 @@ class DisplayServerX11 : public DisplayServer {
HashMap<int, Vector2> pen_pressure_range;
HashMap<int, Vector2> pen_tilt_x_range;
HashMap<int, Vector2> pen_tilt_y_range;
+ HashMap<int, bool> pen_inverted_devices;
XIEventMask all_event_mask;
HashMap<int, Vector2> state;
double pressure;
bool pressure_supported;
+ bool pen_inverted;
Vector2 tilt;
Vector2 mouse_pos_to_filter;
Vector2 relative_motion;
@@ -265,6 +267,7 @@ class DisplayServerX11 : public DisplayServer {
void _update_real_mouse_position(const WindowData &wd);
bool _window_maximize_check(WindowID p_window, const char *p_atom_name) const;
+ bool _window_fullscreen_check(WindowID p_window) const;
void _update_size_hints(WindowID p_window);
void _set_wm_fullscreen(WindowID p_window, bool p_enabled);
void _set_wm_maximized(WindowID p_window, bool p_enabled);
diff --git a/platform/linuxbsd/export/export.cpp b/platform/linuxbsd/export/export.cpp
index 965b969ba8..4240e9adc0 100644
--- a/platform/linuxbsd/export/export.cpp
+++ b/platform/linuxbsd/export/export.cpp
@@ -35,12 +35,7 @@
void register_linuxbsd_exporter() {
Ref<EditorExportPlatformLinuxBSD> platform;
platform.instantiate();
-
- Ref<Image> img = memnew(Image(_linuxbsd_logo));
- Ref<ImageTexture> logo;
- logo.instantiate();
- logo->create_from_image(img);
- platform->set_logo(logo);
+ platform->set_logo(ImageTexture::create_from_image(memnew(Image(_linuxbsd_logo))));
platform->set_name("Linux/X11");
platform->set_extension("x86_32");
platform->set_extension("x86_64", "binary_format/64_bits");
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index 9fe00568fb..91a260182e 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -61,6 +61,10 @@ int main(int argc, char *argv[]) {
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
if (err != OK) {
free(cwd);
+
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return 0;
+ }
return 255;
}
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 8d848d2094..47765cff71 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -24,7 +24,7 @@ def get_opts():
return [
("osxcross_sdk", "OSXCross SDK version", "darwin16"),
("MACOS_SDK_PATH", "Path to the macOS SDK", ""),
- ("VULKAN_SDK_PATH", "Path to the Vulkan SDK", ""),
+ ("vulkan_sdk_path", "Path to the Vulkan SDK", ""),
EnumVariable("macports_clang", "Build using Clang from MacPorts", "no", ("no", "5.0", "devel")),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
@@ -36,7 +36,38 @@ def get_opts():
def get_flags():
- return []
+ return [
+ ("use_volk", False),
+ ]
+
+
+def get_mvk_sdk_path():
+ def int_or_zero(i):
+ try:
+ return int(i)
+ except:
+ return 0
+
+ def ver_parse(a):
+ return [int_or_zero(i) for i in a.split(".")]
+
+ dirname = os.path.expanduser("~/VulkanSDK")
+ files = os.listdir(dirname)
+
+ ver_file = "0.0.0.0"
+ ver_num = ver_parse(ver_file)
+
+ for file in files:
+ if os.path.isdir(os.path.join(dirname, file)):
+ ver_comp = ver_parse(file)
+ lib_name = os.path.join(
+ os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a"
+ )
+ if os.path.isfile(lib_name) and ver_comp > ver_num:
+ ver_num = ver_comp
+ ver_file = file
+
+ return os.path.join(os.path.join(dirname, ver_file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/")
def configure(env):
@@ -79,10 +110,12 @@ def configure(env):
if env["arch"] == "arm64":
print("Building for macOS 11.0+, platform arm64.")
+ env.Append(ASFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
else:
print("Building for macOS 10.12+, platform x86_64.")
+ env.Append(ASFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
@@ -197,4 +230,22 @@ def configure(env):
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
env.Append(LINKFLAGS=["-framework", "Metal", "-framework", "QuartzCore", "-framework", "IOSurface"])
if not env["use_volk"]:
- env.Append(LINKFLAGS=["-L$VULKAN_SDK_PATH/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/", "-lMoltenVK"])
+ env.Append(LINKFLAGS=["-lMoltenVK"])
+ mvk_found = False
+ if env["vulkan_sdk_path"] != "":
+ mvk_path = os.path.join(
+ os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/"
+ )
+ if os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
+ mvk_found = True
+ env.Append(LINKFLAGS=["-L" + mvk_path])
+ if not mvk_found:
+ mvk_path = get_mvk_sdk_path()
+ if os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
+ mvk_found = True
+ env.Append(LINKFLAGS=["-L" + mvk_path])
+ if not mvk_found:
+ print(
+ "MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path."
+ )
+ sys.exit(255)
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index b6a5813bd0..91d64b50f0 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -1178,10 +1178,7 @@ Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_
GodotMenuItem *obj = [menu_item representedObject];
if (obj) {
if (obj->img.is_valid()) {
- Ref<ImageTexture> txt;
- txt.instantiate();
- txt->create_from_image(obj->img);
- return txt;
+ return ImageTexture::create_from_image(obj->img);
}
}
}
@@ -2920,7 +2917,9 @@ void DisplayServerOSX::make_rendering_thread() {
void DisplayServerOSX::swap_buffers() {
#if defined(GLES3_ENABLED)
- gl_manager->swap_buffers();
+ if (gl_manager) {
+ gl_manager->swap_buffers();
+ }
#endif
}
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 7010709123..a22d7e5e3d 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -252,7 +252,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
if (icon_infos[i].is_png) {
// Encode PNG icon.
- it->create_from_image(copy);
+ it->set_image(copy);
String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png");
ResourceSaver::save(path, it);
@@ -1086,6 +1086,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
+ f.unref();
if (is_execute) {
// chmod with 0755 if the file is executable.
FileAccess::set_unix_permissions(file, 0755);
@@ -1665,9 +1666,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
}
EditorExportPlatformOSX::EditorExportPlatformOSX() {
- Ref<Image> img = memnew(Image(_osx_logo));
- logo.instantiate();
- logo->create_from_image(img);
+ logo = ImageTexture::create_from_image(memnew(Image(_osx_logo)));
}
EditorExportPlatformOSX::~EditorExportPlatformOSX() {
diff --git a/platform/osx/godot_application_delegate.h b/platform/osx/godot_application_delegate.h
index 8eec762d8f..f5b67b580f 100644
--- a/platform/osx/godot_application_delegate.h
+++ b/platform/osx/godot_application_delegate.h
@@ -40,6 +40,7 @@
- (void)forceUnbundledWindowActivationHackStep1;
- (void)forceUnbundledWindowActivationHackStep2;
- (void)forceUnbundledWindowActivationHackStep3;
+- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
@end
#endif // GODOT_APPLICATION_DELEGATE_H
diff --git a/platform/osx/godot_application_delegate.mm b/platform/osx/godot_application_delegate.mm
index dc82075c44..4d3558b273 100644
--- a/platform/osx/godot_application_delegate.mm
+++ b/platform/osx/godot_application_delegate.mm
@@ -67,6 +67,52 @@
}
}
+- (id)init {
+ self = [super init];
+
+ NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
+ [aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
+ [aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
+
+ return self;
+}
+
+- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+ OS_OSX *os = (OS_OSX *)OS::get_singleton();
+ if (!event || !os) {
+ return;
+ }
+
+ List<String> args;
+ if (([event eventClass] == kInternetEventClass) && ([event eventID] == kAEGetURL)) {
+ // Opening URL scheme.
+ NSString *url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+ args.push_back(vformat("--uri=\"%s\"", String::utf8([url UTF8String])));
+ }
+
+ if (([event eventClass] == kCoreEventClass) && ([event eventID] == kAEOpenDocuments)) {
+ // Opening file association.
+ NSAppleEventDescriptor *files = [event paramDescriptorForKeyword:keyDirectObject];
+ if (files) {
+ NSInteger count = [files numberOfItems];
+ for (NSInteger i = 1; i <= count; i++) {
+ NSURL *url = [NSURL URLWithString:[[files descriptorAtIndex:i] stringValue]];
+ args.push_back(String::utf8([url.path UTF8String]));
+ }
+ }
+ }
+
+ if (!args.is_empty()) {
+ if (os->get_main_loop()) {
+ // Application is already running, open a new instance with the URL/files as command line arguments.
+ os->create_instance(args);
+ } else {
+ // Application is just started, add to the list of command line arguments and continue.
+ os->set_cmdline_platform_args(args);
+ }
+ }
+}
+
- (void)applicationDidResignActive:(NSNotification *)notification {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
@@ -99,25 +145,6 @@
}
}
-- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
- // Note: may be called called before main loop init!
- OS_OSX *os = (OS_OSX *)OS::get_singleton();
- if (os) {
- os->set_open_with_filename(String::utf8([filename UTF8String]));
- }
-
-#ifdef TOOLS_ENABLED
- // Open new instance.
- if (os && os->get_main_loop()) {
- List<String> args;
- args.push_back(os->get_open_with_filename());
- String exec = os->get_executable_path();
- os->create_process(exec, args);
- }
-#endif
- return YES;
-}
-
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
diff --git a/platform/osx/godot_content_view.h b/platform/osx/godot_content_view.h
index 7942d716dc..353305aec1 100644
--- a/platform/osx/godot_content_view.h
+++ b/platform/osx/godot_content_view.h
@@ -52,6 +52,7 @@
bool ime_input_event_in_progress;
bool mouse_down_control;
bool ignore_momentum_scroll;
+ bool last_pen_inverted;
}
- (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor;
diff --git a/platform/osx/godot_content_view.mm b/platform/osx/godot_content_view.mm
index e96f0a8098..018b90e629 100644
--- a/platform/osx/godot_content_view.mm
+++ b/platform/osx/godot_content_view.mm
@@ -42,6 +42,7 @@
ime_input_event_in_progress = false;
mouse_down_control = false;
ignore_momentum_scroll = false;
+ last_pen_inverted = false;
[self updateTrackingAreas];
if (@available(macOS 10.13, *)) {
@@ -377,9 +378,15 @@
ds->update_mouse_pos(wd, mpos);
mm->set_position(wd.mouse_pos);
mm->set_pressure([event pressure]);
- if ([event subtype] == NSEventSubtypeTabletPoint) {
+ NSEventSubtype subtype = [event subtype];
+ if (subtype == NSEventSubtypeTabletPoint) {
const NSPoint p = [event tilt];
mm->set_tilt(Vector2(p.x, p.y));
+ mm->set_pen_inverted(last_pen_inverted);
+ } else if (subtype == NSEventSubtypeTabletProximity) {
+ // Check if using the eraser end of pen only on proximity event.
+ last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser;
+ mm->set_pen_inverted(last_pen_inverted);
}
mm->set_global_position(wd.mouse_pos);
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index 053a7f4a1d..722928ad60 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -74,16 +74,11 @@ int main(int argc, char **argv) {
// We must override main when testing is enabled.
TEST_MAIN_OVERRIDE
- if (os.get_open_with_filename() != "") {
- char *argv_c = (char *)malloc(os.get_open_with_filename().utf8().size());
- memcpy(argv_c, os.get_open_with_filename().utf8().get_data(), os.get_open_with_filename().utf8().size());
- err = Main::setup(argv[0], 1, &argv_c);
- free(argv_c);
- } else {
- err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
- }
+ err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
- if (err != OK) {
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return 0;
+ } else if (err != OK) {
return 255;
}
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index e4ec411c96..b105be4a06 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -57,7 +57,7 @@ class OS_OSX : public OS_Unix {
MainLoop *main_loop = nullptr;
- String open_with_filename;
+ List<String> launch_service_args;
static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
static void pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context);
@@ -73,8 +73,8 @@ protected:
virtual void delete_main_loop() override;
public:
- String get_open_with_filename() const;
- void set_open_with_filename(const String &p_path);
+ virtual void set_cmdline_platform_args(const List<String> &p_args);
+ virtual List<String> get_cmdline_platform_args() const override;
virtual String get_name() const override;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index a8fa56e34b..5230ed4155 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -121,12 +121,12 @@ void OS_OSX::delete_main_loop() {
main_loop = nullptr;
}
-String OS_OSX::get_open_with_filename() const {
- return open_with_filename;
+void OS_OSX::set_cmdline_platform_args(const List<String> &p_args) {
+ launch_service_args = p_args;
}
-void OS_OSX::set_open_with_filename(const String &p_path) {
- open_with_filename = p_path;
+List<String> OS_OSX::get_cmdline_platform_args() const {
+ return launch_service_args;
}
String OS_OSX::get_name() const {
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
index 01683c656c..19b43d50be 100644
--- a/platform/uwp/export/export_plugin.cpp
+++ b/platform/uwp/export/export_plugin.cpp
@@ -503,7 +503,5 @@ void EditorExportPlatformUWP::resolve_platform_feature_priorities(const Ref<Edit
}
EditorExportPlatformUWP::EditorExportPlatformUWP() {
- Ref<Image> img = memnew(Image(_uwp_logo));
- logo.instantiate();
- logo->create_from_image(img);
+ logo = ImageTexture::create_from_image(memnew(Image(_uwp_logo)));
}
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 998b0882b3..e66fa142a7 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -656,7 +656,9 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) {
#if defined(GLES3_ENABLED)
- gl_manager->window_make_current(p_window_id);
+ if (gl_manager) {
+ gl_manager->window_make_current(p_window_id);
+ }
#endif
}
@@ -2490,6 +2492,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
windows[window_id].last_tilt = Vector2();
}
+ windows[window_id].last_pen_inverted = packet.pkStatus & TPS_INVERT;
+
POINT coords;
GetCursorPos(&coords);
ScreenToClient(windows[window_id].hWnd, &coords);
@@ -2508,6 +2512,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
+ mm->set_pen_inverted(windows[window_id].last_pen_inverted);
mm->set_button_mask(last_button_state);
@@ -2640,6 +2645,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if ((pen_info.penMask & PEN_MASK_TILT_X) && (pen_info.penMask & PEN_MASK_TILT_Y)) {
mm->set_tilt(Vector2((float)pen_info.tiltX / 90, (float)pen_info.tiltY / 90));
}
+ mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER));
mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
@@ -2742,14 +2748,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} else {
windows[window_id].last_tilt = Vector2();
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
+ windows[window_id].last_pen_inverted = false;
}
} else {
windows[window_id].last_tilt = Vector2();
windows[window_id].last_pressure = (wParam & MK_LBUTTON) ? 1.0f : 0.0f;
+ windows[window_id].last_pen_inverted = false;
}
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
+ mm->set_pen_inverted(windows[window_id].last_pen_inverted);
mm->set_button_mask(last_button_state);
@@ -3360,8 +3369,8 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
if ((p_new_driver == "wintab") && wintab_available) {
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
wd.wtlc.lcOptions |= CXO_MESSAGES;
- wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
- wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
+ wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
+ wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
wd.wtlc.lcPktMode = 0;
wd.wtlc.lcOutOrgX = 0;
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
@@ -3484,8 +3493,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
if ((tablet_get_current_driver() == "wintab") && wintab_available) {
wintab_WTInfo(WTI_DEFSYSCTX, 0, &wd.wtlc);
wd.wtlc.lcOptions |= CXO_MESSAGES;
- wd.wtlc.lcPktData = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
- wd.wtlc.lcMoveMask = PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
+ wd.wtlc.lcPktData = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION;
+ wd.wtlc.lcMoveMask = PK_STATUS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE;
wd.wtlc.lcPktMode = 0;
wd.wtlc.lcOutOrgX = 0;
wd.wtlc.lcOutExtX = wd.wtlc.lcInExtX;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index fc89517774..0429bed3a0 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -82,10 +82,13 @@
#define DVC_ROTATION 18
#define CXO_MESSAGES 0x0004
+#define PK_STATUS 0x0002
#define PK_NORMAL_PRESSURE 0x0400
#define PK_TANGENT_PRESSURE 0x0800
#define PK_ORIENTATION 0x1000
+#define TPS_INVERT 0x0010 /* 1.1 */
+
typedef struct tagLOGCONTEXTW {
WCHAR lcName[40];
UINT lcOptions;
@@ -137,6 +140,7 @@ typedef struct tagORIENTATION {
} ORIENTATION;
typedef struct tagPACKET {
+ int pkStatus;
int pkNormalPressure;
int pkTangentPressure;
ORIENTATION pkOrientation;
@@ -158,6 +162,14 @@ typedef UINT32 POINTER_FLAGS;
typedef UINT32 PEN_FLAGS;
typedef UINT32 PEN_MASK;
+#ifndef PEN_FLAG_INVERTED
+#define PEN_FLAG_INVERTED 0x00000002
+#endif
+
+#ifndef PEN_FLAG_ERASER
+#define PEN_FLAG_ERASER 0x00000004
+#endif
+
#ifndef PEN_MASK_PRESSURE
#define PEN_MASK_PRESSURE 0x00000001
#endif
@@ -357,11 +369,13 @@ class DisplayServerWindows : public DisplayServer {
int min_pressure;
int max_pressure;
bool tilt_supported;
+ bool pen_inverted = false;
bool block_mm = false;
int last_pressure_update;
float last_pressure;
Vector2 last_tilt;
+ bool last_pen_inverted = false;
HBITMAP hBitmap; //DIB section for layered window
uint8_t *dib_data = nullptr;
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 0fa2913218..af19f24f09 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -48,12 +48,7 @@ void register_windows_exporter() {
Ref<EditorExportPlatformWindows> platform;
platform.instantiate();
-
- Ref<Image> img = memnew(Image(_windows_logo));
- Ref<ImageTexture> logo;
- logo.instantiate();
- logo->create_from_image(img);
- platform->set_logo(logo);
+ platform->set_logo(ImageTexture::create_from_image(memnew(Image(_windows_logo))));
platform->set_name("Windows Desktop");
platform->set_os_name("Windows");
diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp
index 8de3ef294a..72920d2816 100644
--- a/platform/windows/godot_windows.cpp
+++ b/platform/windows/godot_windows.cpp
@@ -166,6 +166,10 @@ int widechar_main(int argc, wchar_t **argv) {
delete[] argv_utf8[i];
}
delete[] argv_utf8;
+
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return 0;
+ }
return 255;
}
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 221d52bc20..d56c7b8811 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -138,8 +138,11 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame") {
property.hint = PROPERTY_HINT_RANGE;
- if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) {
+ if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) {
property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1";
+ } else {
+ // Avoid an error, `hint_string` is required for `PROPERTY_HINT_RANGE`.
+ property.hint_string = "0,0,1";
}
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index 913003c7e6..4155d0797f 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -243,7 +243,7 @@ bool CPUParticles2D::get_fractional_delta() const {
}
TypedArray<String> CPUParticles2D::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+ TypedArray<String> warnings = Node2D::get_configuration_warnings();
CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr());
@@ -314,6 +314,8 @@ void CPUParticles2D::set_param_max(Parameter p_param, real_t p_value) {
if (parameters_min[p_param] > parameters_max[p_param]) {
set_param_min(p_param, p_value);
}
+
+ update_configuration_warnings();
}
real_t CPUParticles2D::get_param_max(Parameter p_param) const {
@@ -374,6 +376,8 @@ void CPUParticles2D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
default: {
}
}
+
+ update_configuration_warnings();
}
Ref<Curve> CPUParticles2D::get_param_curve(Parameter p_param) const {
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 6edd75e62a..a869cf2525 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -141,7 +141,6 @@ void GPUParticles2D::set_process_material(const Ref<Material> &p_material) {
void GPUParticles2D::set_trail_enabled(bool p_enabled) {
trail_enabled = p_enabled;
RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
- update_configuration_warnings();
update();
RS::get_singleton()->particles_set_transform_align(particles, p_enabled ? RS::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY : RS::PARTICLES_TRANSFORM_ALIGN_DISABLED);
@@ -297,7 +296,7 @@ bool GPUParticles2D::get_interpolate() const {
}
TypedArray<String> GPUParticles2D::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+ TypedArray<String> warnings = Node2D::get_configuration_warnings();
if (RenderingServer::get_singleton()->is_low_end()) {
warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" option for this purpose."));
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 9c4b0feea2..cf8b6b8f94 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1158,6 +1158,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
rs->canvas_item_set_transform(canvas_item, xform);
rs->canvas_item_set_light_mask(canvas_item, get_light_mask());
+ rs->canvas_item_set_z_as_relative_to_parent(canvas_item, true);
rs->canvas_item_set_z_index(canvas_item, z_index);
rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(get_texture_filter()));
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index d0aeffb166..fbd5b5b65b 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -376,6 +376,24 @@ void BoneAttachment3D::on_bone_pose_update(int p_bone_index) {
}
}
}
+#ifdef TOOLS_ENABLED
+void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map) {
+ const Skeleton3D *parent = nullptr;
+ if (use_external_skeleton) {
+ if (external_skeleton_node_cache.is_valid()) {
+ parent = Object::cast_to<Skeleton3D>(ObjectDB::get_instance(external_skeleton_node_cache));
+ }
+ } else {
+ parent = Object::cast_to<Skeleton3D>(get_parent());
+ }
+ if (parent && parent == p_skeleton) {
+ StringName bn = p_bone_map->find_profile_bone_name(bone_name);
+ if (bn) {
+ set_bone_name(bn);
+ }
+ }
+}
+#endif // TOOLS_ENABLED
BoneAttachment3D::BoneAttachment3D() {
}
@@ -398,6 +416,9 @@ void BoneAttachment3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_use_external_skeleton"), &BoneAttachment3D::get_use_external_skeleton);
ClassDB::bind_method(D_METHOD("set_external_skeleton", "external_skeleton"), &BoneAttachment3D::set_external_skeleton);
ClassDB::bind_method(D_METHOD("get_external_skeleton"), &BoneAttachment3D::get_external_skeleton);
+#ifdef TOOLS_ENABLED
+ ClassDB::bind_method(D_METHOD("_notify_skeleton_bones_renamed"), &BoneAttachment3D::_notify_skeleton_bones_renamed);
+#endif // TOOLS_ENABLED
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_idx"), "set_bone_idx", "get_bone_idx");
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index 395dfde1d7..137360b141 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -32,6 +32,9 @@
#define BONE_ATTACHMENT_H
#include "scene/3d/skeleton_3d.h"
+#ifdef TOOLS_ENABLED
+#include "scene/resources/bone_map.h"
+#endif // TOOLS_ENABLED
class BoneAttachment3D : public Node3D {
GDCLASS(BoneAttachment3D, Node3D);
@@ -68,6 +71,9 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+#ifdef TOOLS_ENABLED
+ virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map);
+#endif // TOOLS_ENABLED
public:
virtual TypedArray<String> get_configuration_warnings() const override;
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 8585f3bdfc..4df0c37ad6 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -164,6 +164,8 @@ void CPUParticles3D::set_mesh(const Ref<Mesh> &p_mesh) {
} else {
RS::get_singleton()->multimesh_set_mesh(multimesh, RID());
}
+
+ update_configuration_warnings();
}
Ref<Mesh> CPUParticles3D::get_mesh() const {
@@ -187,7 +189,7 @@ bool CPUParticles3D::get_fractional_delta() const {
}
TypedArray<String> CPUParticles3D::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+ TypedArray<String> warnings = GeometryInstance3D::get_configuration_warnings();
bool mesh_found = false;
bool anim_material_found = false;
@@ -266,6 +268,8 @@ void CPUParticles3D::set_param_min(Parameter p_param, real_t p_value) {
if (parameters_min[p_param] > parameters_max[p_param]) {
set_param_max(p_param, p_value);
}
+
+ update_configuration_warnings();
}
real_t CPUParticles3D::get_param_min(Parameter p_param) const {
@@ -276,10 +280,13 @@ real_t CPUParticles3D::get_param_min(Parameter p_param) const {
void CPUParticles3D::set_param_max(Parameter p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
+
parameters_max[p_param] = p_value;
if (parameters_min[p_param] > parameters_max[p_param]) {
set_param_min(p_param, p_value);
}
+
+ update_configuration_warnings();
}
real_t CPUParticles3D::get_param_max(Parameter p_param) const {
@@ -340,6 +347,8 @@ void CPUParticles3D::set_param_curve(Parameter p_param, const Ref<Curve> &p_curv
default: {
}
}
+
+ update_configuration_warnings();
}
Ref<Curve> CPUParticles3D::get_param_curve(Parameter p_param) const {
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index ab07f33ace..01cab493ec 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -72,7 +72,7 @@ real_t Decal::get_albedo_mix() const {
}
void Decal::set_upper_fade(real_t p_fade) {
- upper_fade = p_fade;
+ upper_fade = MAX(p_fade, 0.0);
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
@@ -81,7 +81,7 @@ real_t Decal::get_upper_fade() const {
}
void Decal::set_lower_fade(real_t p_fade) {
- lower_fade = p_fade;
+ lower_fade = MAX(p_fade, 0.0);
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index d18c452ca7..b352114c7f 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -270,7 +270,7 @@ bool GPUParticles3D::get_interpolate() const {
}
TypedArray<String> GPUParticles3D::get_configuration_warnings() const {
- TypedArray<String> warnings = Node::get_configuration_warnings();
+ TypedArray<String> warnings = GeometryInstance3D::get_configuration_warnings();
if (RenderingServer::get_singleton()->is_low_end()) {
warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose."));
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index 0849b2c631..0e5771bdb1 100644
--- a/scene/3d/label_3d.cpp
+++ b/scene/3d/label_3d.cpp
@@ -53,10 +53,6 @@ void Label3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label3D::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Label3D::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label3D::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label3D::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label3D::clear_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_language", "language"), &Label3D::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Label3D::get_language);
@@ -140,7 +136,7 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1,suffix:px"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,suffix:px"), "set_outline_size", "get_outline_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
@@ -148,12 +144,12 @@ void Label3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:px"), "set_width", "get_width");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
- ADD_GROUP("Locale", "");
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
BIND_ENUM_CONSTANT(FLAG_SHADED);
BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED);
@@ -166,56 +162,6 @@ void Label3D::_bind_methods() {
BIND_ENUM_CONSTANT(ALPHA_CUT_OPAQUE_PREPASS);
}
-bool Label3D::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- dirty_font = true;
- _queue_update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- dirty_font = true;
- _queue_update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool Label3D::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void Label3D::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
void Label3D::_validate_property(PropertyInfo &property) const {
if (property.name == "material_override" || property.name == "material_overlay") {
property.usage = PROPERTY_USAGE_NO_EDITOR;
@@ -280,7 +226,7 @@ Ref<TriangleMesh> Label3D::generate_triangle_mesh() const {
float total_h = 0.0;
float max_line_w = 0.0;
for (int i = 0; i < lines_rid.size(); i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
max_line_w = MAX(max_line_w, TS->shaped_text_get_width(lines_rid[i]));
}
@@ -370,15 +316,8 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset,
bool msdf = TS->font_is_multichannel_signed_distance_field(p_glyph.font_rid);
- uint64_t mat_hash;
- if (tex != RID()) {
- mat_hash = hash_one_uint64(tex.get_id());
- } else {
- mat_hash = hash_one_uint64(0);
- }
- mat_hash = hash_fmix32(hash_murmur3_one_64(p_priority | (p_outline_size << 31), mat_hash));
-
- if (!surfaces.has(mat_hash)) {
+ SurfaceKey key = SurfaceKey(tex.get_id(), p_priority, p_outline_size);
+ if (!surfaces.has(key)) {
SurfaceData surf;
surf.material = RenderingServer::get_singleton()->material_create();
// Set defaults for material, names need to match up those in StandardMaterial3D
@@ -407,9 +346,9 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset,
surf.z_shift = p_priority * pixel_size;
}
- surfaces[mat_hash] = surf;
+ surfaces[key] = surf;
}
- SurfaceData &s = surfaces[mat_hash];
+ SurfaceData &s = surfaces[key];
s.mesh_vertices.resize((s.offset + 1) * 4);
s.mesh_normals.resize((s.offset + 1) * 4);
@@ -464,7 +403,7 @@ void Label3D::_shape() {
aabb = AABB();
// Clear materials.
- for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) {
+ for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) {
RenderingServer::get_singleton()->free(E.value.material);
}
surfaces.clear();
@@ -478,7 +417,10 @@ void Label3D::_shape() {
TS->shaped_text_set_direction(text_rid, text_direction);
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
- TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language);
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
Array stt;
if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
@@ -494,7 +436,10 @@ void Label3D::_shape() {
} else if (dirty_font) {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
- TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
+ }
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
dirty_font = false;
@@ -541,7 +486,7 @@ void Label3D::_shape() {
// Generate surfaces and materials.
float total_h = 0.0;
for (int i = 0; i < lines_rid.size(); i++) {
- total_h += (TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing) * pixel_size;
+ total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size;
}
float vbegin = 0.0;
@@ -577,7 +522,7 @@ void Label3D::_shape() {
} break;
}
offset.x += lbl_offset.x * pixel_size;
- offset.y -= (TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP)) * pixel_size;
+ offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
if (outline_modulate.a != 0.0 && outline_size > 0) {
// Outline surfaces.
@@ -591,10 +536,10 @@ void Label3D::_shape() {
for (int j = 0; j < gl_size; j++) {
_generate_glyph_surfaces(glyphs[j], offset, modulate, render_priority);
}
- offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size;
+ offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
}
- for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) {
+ for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) {
Array mesh_array;
mesh_array.resize(RS::ARRAY_MAX);
mesh_array[RS::ARRAY_VERTEX] = E.value.mesh_vertices;
@@ -664,29 +609,6 @@ TextServer::Direction Label3D::get_text_direction() const {
return text_direction;
}
-void Label3D::clear_opentype_features() {
- opentype_features.clear();
- dirty_font = true;
- _queue_update();
-}
-
-void Label3D::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- dirty_font = true;
- _queue_update();
- }
-}
-
-int Label3D::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void Label3D::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -788,7 +710,7 @@ Ref<Font> Label3D::_get_font_or_default() const {
theme_font.unref();
}
- if (font_override.is_valid() && font_override->get_data_count() > 0) {
+ if (font_override.is_valid()) {
return font_override;
}
@@ -1018,7 +940,7 @@ Label3D::~Label3D() {
TS->free_rid(text_rid);
RenderingServer::get_singleton()->free(mesh);
- for (KeyValue<uint64_t, SurfaceData> E : surfaces) {
+ for (KeyValue<SurfaceKey, SurfaceData> E : surfaces) {
RenderingServer::get_singleton()->free(E.value.material);
}
surfaces.clear();
diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h
index 7766bca068..4498e89517 100644
--- a/scene/3d/label_3d.h
+++ b/scene/3d/label_3d.h
@@ -76,7 +76,29 @@ private:
RID material;
};
- HashMap<uint64_t, SurfaceData> surfaces;
+ struct SurfaceKey {
+ uint64_t texture_id;
+ int32_t priority;
+ int32_t outline_size;
+
+ bool operator==(const SurfaceKey &p_b) const {
+ return (texture_id == p_b.texture_id) && (priority == p_b.priority) && (outline_size == p_b.outline_size);
+ }
+
+ SurfaceKey(uint64_t p_texture_id, int p_priority, int p_outline_size) {
+ texture_id = p_texture_id;
+ priority = p_priority;
+ outline_size = p_outline_size;
+ }
+ };
+
+ struct SurfaceKeyHasher {
+ _FORCE_INLINE_ static uint32_t hash(const SurfaceKey &p_a) {
+ return hash_murmur3_buffer(&p_a, sizeof(SurfaceKey));
+ }
+ };
+
+ HashMap<SurfaceKey, SurfaceData, SurfaceKeyHasher> surfaces;
HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;
VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;
@@ -100,7 +122,6 @@ private:
float line_spacing = 0.f;
- Dictionary opentype_features;
String language;
TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@@ -128,9 +149,6 @@ protected:
static void _bind_methods();
- 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;
void _validate_property(PropertyInfo &property) const override;
void _im_update();
@@ -158,10 +176,6 @@ public:
void set_text_direction(TextServer::Direction p_text_direction);
TextServer::Direction get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 4c00250162..04b1081516 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -237,6 +237,28 @@ void Node3D::set_quaternion(const Quaternion &p_quaternion) {
}
}
+Vector3 Node3D::get_global_position() const {
+ return get_global_transform().get_origin();
+}
+
+void Node3D::set_global_position(const Vector3 &p_position) {
+ Transform3D transform = get_global_transform();
+ transform.set_origin(p_position);
+ set_global_transform(transform);
+}
+
+Vector3 Node3D::get_global_rotation() const {
+ return get_global_transform().get_basis().get_euler();
+}
+
+void Node3D::set_global_rotation(const Vector3 &p_euler_rad) {
+ Transform3D transform = get_global_transform();
+ Basis new_basis = transform.get_basis();
+ new_basis.set_euler(p_euler_rad);
+ transform.set_basis(new_basis);
+ set_global_transform(transform);
+}
+
void Node3D::set_transform(const Transform3D &p_transform) {
data.local_transform = p_transform;
data.dirty = DIRTY_EULER_ROTATION_AND_SCALE; // Make rot/scale dirty.
@@ -950,8 +972,14 @@ void Node3D::_bind_methods() {
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("set_global_position", "position"), &Node3D::set_global_position);
+ ClassDB::bind_method(D_METHOD("get_global_position"), &Node3D::get_global_position);
+ ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node3D::set_global_rotation);
+ ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node3D::get_global_rotation);
+
ClassDB::bind_method(D_METHOD("get_parent_node_3d"), &Node3D::get_parent_node_3d);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification);
ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &Node3D::set_as_top_level);
@@ -1034,6 +1062,9 @@ void Node3D::_bind_methods() {
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_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_position", "get_global_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "global_rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_rotation", "get_global_rotation");
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 cfd88585e4..b1e129798d 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -182,12 +182,18 @@ public:
void set_rotation(const Vector3 &p_euler_rad);
void set_scale(const Vector3 &p_scale);
+ void set_global_position(const Vector3 &p_position);
+ void set_global_rotation(const Vector3 &p_euler_rad);
+
Vector3 get_position() const;
RotationOrder get_rotation_order() const;
Vector3 get_rotation() const;
Vector3 get_scale() const;
+ Vector3 get_global_position() const;
+ Vector3 get_global_rotation() const;
+
void set_transform(const Transform3D &p_transform);
void set_basis(const Basis &p_basis);
void set_quaternion(const Quaternion &p_quaternion);
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 55b55d924c..cb6354f7a8 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -1034,8 +1034,11 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame") {
property.hint = PROPERTY_HINT_RANGE;
- if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) {
+ if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) {
property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1";
+ } else {
+ // Avoid an error, `hint_string` is required for `PROPERTY_HINT_RANGE`.
+ property.hint_string = "0,0,1";
}
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index d81b59b3fc..ae231026a7 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -272,7 +272,8 @@ VoxelGI::Subdiv VoxelGI::get_subdiv() const {
}
void VoxelGI::set_extents(const Vector3 &p_extents) {
- extents = p_extents;
+ // Prevent very small extents as these break baking if other extents are set very high.
+ extents = Vector3(MAX(1.0, p_extents.x), MAX(1.0, p_extents.y), MAX(1.0, p_extents.z));
update_gizmos();
}
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 1371c9cd57..d8de22d27c 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -347,7 +347,6 @@ void Button::_notification(int p_what) {
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
-
text_buf->draw(ci, text_ofs, color);
} break;
}
@@ -363,7 +362,7 @@ void Button::_shape() {
} else {
text_buf->set_direction((TextServer::Direction)text_direction);
}
- text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ text_buf->add_string(xl_text, font, font_size, language);
text_buf->set_text_overrun_behavior(overrun_behavior);
}
@@ -409,29 +408,6 @@ Control::TextDirection Button::get_text_direction() const {
return text_direction;
}
-void Button::clear_opentype_features() {
- opentype_features.clear();
- _shape();
- update();
-}
-
-void Button::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- _shape();
- update();
- }
-}
-
-int Button::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void Button::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -512,56 +488,6 @@ HorizontalAlignment Button::get_icon_alignment() const {
return icon_alignment;
}
-bool Button::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- _shape();
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- _shape();
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool Button::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void Button::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
@@ -569,9 +495,6 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Button::get_text_overrun_behavior);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Button::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Button::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Button::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon);
@@ -588,8 +511,6 @@ void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_expand_icon"), &Button::is_expand_icon);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
@@ -597,6 +518,10 @@ void Button::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::INT, "icon_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_icon_alignment", "get_icon_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_icon"), "set_expand_icon", "is_expand_icon");
+
+ ADD_GROUP("BiDi", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
}
Button::Button(const String &p_text) {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index a1d71195cb..7a29cba677 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -43,7 +43,6 @@ private:
String xl_text;
Ref<TextParagraph> text_buf;
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING;
@@ -62,10 +61,6 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- 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;
-
public:
virtual Size2 get_minimum_size() const override;
@@ -78,10 +73,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 22e9763929..22f968eac7 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -46,7 +46,7 @@ void CodeEdit::_notification(int p_what) {
line_spacing = get_theme_constant(SNAME("line_spacing"));
set_gutter_width(main_gutter, get_line_height());
- set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
+ set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width);
set_gutter_width(fold_gutter, get_line_height() / 1.2);
breakpoint_color = get_theme_color(SNAME("breakpoint_color"));
@@ -68,6 +68,7 @@ void CodeEdit::_notification(int p_what) {
code_completion_max_lines = get_theme_constant(SNAME("completion_lines"));
code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width"));
code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color"));
+ code_completion_scroll_hovered_color = get_theme_color(SNAME("completion_scroll_hovered_color"));
code_completion_background_color = get_theme_color(SNAME("completion_background_color"));
code_completion_selected_color = get_theme_color(SNAME("completion_selected_color"));
code_completion_existing_color = get_theme_color(SNAME("completion_existing_color"));
@@ -85,7 +86,7 @@ void CodeEdit::_notification(int p_what) {
if (line_length_guideline_columns.size() > 0) {
const int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
const int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
- const float char_size = font->get_char_size('0', 0, font_size).width;
+ const float char_size = font->get_char_size('0', font_size).width;
for (int i = 0; i < line_length_guideline_columns.size(); i++) {
const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll();
@@ -122,7 +123,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, font_size).width;
+ const int code_completion_base_width = font->get_string_size(code_completion_base, HORIZONTAL_ALIGNMENT_LEFT, -1, 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 {
@@ -134,6 +135,9 @@ void CodeEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(code_completion_rect.position, code_completion_rect.size + Size2(scroll_width, 0)), code_completion_background_color);
}
+ code_completion_scroll_rect.position = code_completion_rect.position + Vector2(code_completion_rect.size.width, 0);
+ code_completion_scroll_rect.size = Vector2(scroll_width, code_completion_rect.size.height);
+
code_completion_line_ofs = CLAMP(code_completion_current_selected - lines / 2, 0, code_completion_options_count - lines);
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color);
@@ -174,8 +178,8 @@ void CodeEdit::_notification(int p_what) {
for (int j = 0; j < code_completion_options[l].matches.size(); j++) {
Pair<int, int> match = code_completion_options[l].matches[j];
- int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), font_size).width;
- int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), font_size).width;
+ int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
+ int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width;
draw_rect(Rect2(match_pos + Point2(match_offset, 0), Size2(match_len, row_height)), code_completion_existing_color);
}
@@ -185,9 +189,11 @@ void CodeEdit::_notification(int p_what) {
/* Draw a small scroll rectangle to show a position in the options. */
if (scroll_width) {
+ Color scroll_color = is_code_completion_scroll_hovered || is_code_completion_scroll_pressed ? code_completion_scroll_hovered_color : code_completion_scroll_color;
+
float r = (float)code_completion_max_lines / code_completion_options_count;
float o = (float)code_completion_line_ofs / code_completion_options_count;
- draw_rect(Rect2(code_completion_rect.position.x + code_completion_rect.size.width, code_completion_rect.position.y + o * code_completion_rect.size.y, scroll_width, code_completion_rect.size.y * r), code_completion_scroll_color);
+ draw_rect(Rect2(code_completion_rect.position.x + code_completion_rect.size.width, code_completion_rect.position.y + o * code_completion_rect.size.y, scroll_width, code_completion_rect.size.y * r), scroll_color);
}
}
@@ -202,11 +208,11 @@ void CodeEdit::_notification(int p_what) {
int max_width = 0;
for (int i = 0; i < line_count; i++) {
- max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], font_size).x);
+ max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x);
}
Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (line_spacing * line_count - 1));
- int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), font_size).x;
+ int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
if (code_hint_xpos == -0xFFFF) {
code_hint_xpos = get_caret_draw_pos().x - offset;
}
@@ -226,8 +232,8 @@ void CodeEdit::_notification(int p_what) {
int begin = 0;
int end = 0;
if (line.contains(String::chr(0xFFFF))) {
- begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), font_size).x;
- end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), font_size).x;
+ begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
+ end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x;
}
Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent(font_size) + font_height * i + yofs);
@@ -260,6 +266,12 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
+ if (is_code_completion_scroll_pressed && mb->get_button_index() == MouseButton::LEFT) {
+ is_code_completion_scroll_pressed = false;
+ update();
+ return;
+ }
+
if (code_completion_active && code_completion_rect.has_point(mb->get_position())) {
if (!mb->is_pressed()) {
return;
@@ -289,7 +301,21 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
return;
+ } else if (code_completion_active && code_completion_scroll_rect.has_point(mb->get_position())) {
+ if (mb->get_button_index() != MouseButton::LEFT) {
+ return;
+ }
+
+ if (mb->is_pressed()) {
+ is_code_completion_scroll_pressed = true;
+
+ _update_scroll_selected_line(mb->get_position().y);
+ update();
+ }
+
+ return;
}
+
cancel_code_completion();
set_code_hint("");
@@ -354,6 +380,18 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
set_symbol_lookup_word_as_valid(false);
}
}
+
+ bool scroll_hovered = code_completion_scroll_rect.has_point(mpos);
+ if (is_code_completion_scroll_hovered != scroll_hovered) {
+ is_code_completion_scroll_hovered = scroll_hovered;
+ update();
+ }
+
+ if (is_code_completion_scroll_pressed) {
+ _update_scroll_selected_line(mpos.y);
+ update();
+ return;
+ }
}
Ref<InputEventKey> k = p_gui_input;
@@ -546,6 +584,10 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
return CURSOR_ARROW;
}
+ if (code_completion_active && code_completion_scroll_rect.has_point(p_pos)) {
+ return CURSOR_ARROW;
+ }
+
Point2i pos = get_line_column_at_pos(p_pos, false);
int line = pos.y;
int col = pos.x;
@@ -2697,6 +2739,13 @@ TypedArray<String> CodeEdit::_get_delimiters(DelimiterType p_type) const {
}
/* Code Completion */
+void CodeEdit::_update_scroll_selected_line(float p_mouse_y) {
+ float percent = (float)(p_mouse_y - code_completion_scroll_rect.position.y) / code_completion_scroll_rect.size.height;
+ percent = CLAMP(percent, 0.0f, 1.0f);
+
+ code_completion_current_selected = (int)(percent * (code_completion_options.size() - 1));
+}
+
void CodeEdit::_filter_code_completion_candidates_impl() {
int line_height = get_line_height();
@@ -2746,7 +2795,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
offset = line_height;
}
- max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
+ max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
code_completion_options.push_back(option);
}
@@ -2857,7 +2906,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
if (string_to_complete.length() == 0) {
code_completion_options.push_back(option);
- max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
+ max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
continue;
}
@@ -2963,7 +3012,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
option.matches.append_array(ssq_matches);
completion_options_subseq.push_back(option);
}
- max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
+ max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
} else if (!*ssq_lower) { // Matched the whole subsequence in s_lower.
option.matches.clear();
@@ -2980,7 +3029,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
option.matches.append_array(ssq_lower_matches);
completion_options_subseq_casei.push_back(option);
}
- max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset);
+ max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset);
}
}
@@ -3036,7 +3085,7 @@ void CodeEdit::_text_changed() {
}
if (font.is_valid()) {
- set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', 0, font_size).width);
+ set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width);
}
lc = get_line_count();
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index ccf046c612..a431d8a5b2 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -203,22 +203,27 @@ private:
int code_completion_max_lines = 7;
int code_completion_scroll_width = 0;
Color code_completion_scroll_color = Color(0, 0, 0, 0);
+ Color code_completion_scroll_hovered_color = Color(0, 0, 0, 0);
Color code_completion_background_color = Color(0, 0, 0, 0);
Color code_completion_selected_color = Color(0, 0, 0, 0);
Color code_completion_existing_color = Color(0, 0, 0, 0);
bool code_completion_active = false;
+ bool is_code_completion_scroll_hovered = false;
+ bool is_code_completion_scroll_pressed = false;
Vector<ScriptLanguage::CodeCompletionOption> code_completion_options;
int code_completion_line_ofs = 0;
int code_completion_current_selected = 0;
int code_completion_longest_line = 0;
Rect2i code_completion_rect;
+ Rect2i code_completion_scroll_rect;
HashSet<char32_t> code_completion_prefixes;
List<ScriptLanguage::CodeCompletionOption> code_completion_option_submitted;
List<ScriptLanguage::CodeCompletionOption> code_completion_option_sources;
String code_completion_base;
+ void _update_scroll_selected_line(float p_mouse_y);
void _filter_code_completion_candidates_impl();
/* Line length guidelines */
diff --git a/scene/gui/color_mode.cpp b/scene/gui/color_mode.cpp
new file mode 100644
index 0000000000..af78d67e5a
--- /dev/null
+++ b/scene/gui/color_mode.cpp
@@ -0,0 +1,330 @@
+/*************************************************************************/
+/* color_mode.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "color_mode.h"
+
+#include "core/math/color.h"
+#include "scene/gui/slider.h"
+#include "thirdparty/misc/ok_color.h"
+
+ColorMode::ColorMode(ColorPicker *p_color_picker) {
+ color_picker = p_color_picker;
+}
+
+String ColorModeRGB::get_slider_label(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 3, String(), "Couldn't get slider label.");
+ return labels[idx];
+}
+
+float ColorModeRGB::get_slider_max(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider max value.");
+ Color color = color_picker->get_pick_color();
+ return next_power_of_2(MAX(255, color.components[idx] * 255.0)) - 1;
+}
+
+float ColorModeRGB::get_slider_value(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider value.");
+ return color_picker->get_pick_color().components[idx] * 255;
+}
+
+Color ColorModeRGB::get_color() const {
+ Vector<float> values = color_picker->get_active_slider_values();
+ Color color;
+ for (int i = 0; i < 4; i++) {
+ color.components[i] = values[i] / 255.0;
+ }
+ return color;
+}
+
+void ColorModeRGB::slider_draw(int p_which) {
+ Vector<Vector2> pos;
+ pos.resize(4);
+ Vector<Color> col;
+ col.resize(4);
+ HSlider *slider = color_picker->get_slider(p_which);
+ Size2 size = slider->get_size();
+ Color left_color;
+ Color right_color;
+ Color color = color_picker->get_pick_color();
+ const real_t margin = 4 * color_picker->get_theme_default_base_scale();
+
+ if (p_which == ColorPicker::SLIDER_COUNT) {
+ slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+
+ left_color = color;
+ left_color.a = 0;
+ right_color = color;
+ right_color.a = 1;
+ } else {
+ left_color = Color(
+ p_which == 0 ? 0 : color.r,
+ p_which == 1 ? 0 : color.g,
+ p_which == 2 ? 0 : color.b);
+ right_color = Color(
+ p_which == 0 ? 1 : color.r,
+ p_which == 1 ? 1 : color.g,
+ p_which == 2 ? 1 : color.b);
+ }
+
+ col.set(0, left_color);
+ col.set(1, right_color);
+ col.set(2, right_color);
+ col.set(3, left_color);
+ pos.set(0, Vector2(0, margin));
+ pos.set(1, Vector2(size.x, margin));
+ pos.set(2, Vector2(size.x, margin * 2));
+ pos.set(3, Vector2(0, margin * 2));
+
+ slider->draw_polygon(pos, col);
+}
+
+String ColorModeHSV::get_slider_label(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 3, String(), "Couldn't get slider label.");
+ return labels[idx];
+}
+
+float ColorModeHSV::get_slider_max(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider max value.");
+ return slider_max[idx];
+}
+
+float ColorModeHSV::get_slider_value(int idx) const {
+ switch (idx) {
+ case 0:
+ return color_picker->get_pick_color().get_h() * 360.0;
+ case 1:
+ return color_picker->get_pick_color().get_s() * 100.0;
+ case 2:
+ return color_picker->get_pick_color().get_v() * 100.0;
+ case 3:
+ return Math::round(color_picker->get_pick_color().components[3] * 255.0);
+ default:
+ ERR_FAIL_V_MSG(0, "Couldn't get slider value.");
+ }
+}
+
+Color ColorModeHSV::get_color() const {
+ Vector<float> values = color_picker->get_active_slider_values();
+ Color color;
+ color.set_hsv(values[0] / 360.0, values[1] / 100.0, values[2] / 100.0, values[3] / 255.0);
+ return color;
+}
+
+void ColorModeHSV::slider_draw(int p_which) {
+ Vector<Vector2> pos;
+ pos.resize(4);
+ Vector<Color> col;
+ col.resize(4);
+ HSlider *slider = color_picker->get_slider(p_which);
+ Size2 size = slider->get_size();
+ Color left_color;
+ Color right_color;
+ Color color = color_picker->get_pick_color();
+ const real_t margin = 4 * color_picker->get_theme_default_base_scale();
+
+ if (p_which == ColorPicker::SLIDER_COUNT) {
+ slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+
+ left_color = color;
+ left_color.a = 0;
+ right_color = color;
+ right_color.a = 1;
+ } else if (p_which == 0) {
+ Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
+ slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
+ slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true);
+ return;
+ } else {
+ Color s_col;
+ Color v_col;
+ s_col.set_hsv(color.get_h(), 0, color.get_v());
+ left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
+ s_col.set_hsv(color.get_h(), 1, color.get_v());
+ v_col.set_hsv(color.get_h(), color.get_s(), 1);
+ right_color = (p_which == 1) ? s_col : v_col;
+ }
+ col.set(0, left_color);
+ col.set(1, right_color);
+ col.set(2, right_color);
+ col.set(3, left_color);
+ pos.set(0, Vector2(0, margin));
+ pos.set(1, Vector2(size.x, margin));
+ pos.set(2, Vector2(size.x, margin * 2));
+ pos.set(3, Vector2(0, margin * 2));
+
+ slider->draw_polygon(pos, col);
+}
+
+String ColorModeRAW::get_slider_label(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 3, String(), "Couldn't get slider label.");
+ return labels[idx];
+}
+
+float ColorModeRAW::get_slider_max(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider max value.");
+ return slider_max[idx];
+}
+
+float ColorModeRAW::get_slider_value(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider value.");
+ return color_picker->get_pick_color().components[idx];
+}
+
+Color ColorModeRAW::get_color() const {
+ Vector<float> values = color_picker->get_active_slider_values();
+ Color color;
+ for (int i = 0; i < 4; i++) {
+ color.components[i] = values[i];
+ }
+ return color;
+}
+
+void ColorModeRAW::slider_draw(int p_which) {
+ Vector<Vector2> pos;
+ pos.resize(4);
+ Vector<Color> col;
+ col.resize(4);
+ HSlider *slider = color_picker->get_slider(p_which);
+ Size2 size = slider->get_size();
+ Color left_color;
+ Color right_color;
+ Color color = color_picker->get_pick_color();
+ const real_t margin = 4 * color_picker->get_theme_default_base_scale();
+
+ if (p_which == ColorPicker::SLIDER_COUNT) {
+ slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+
+ left_color = color;
+ left_color.a = 0;
+ right_color = color;
+ right_color.a = 1;
+
+ col.set(0, left_color);
+ col.set(1, right_color);
+ col.set(2, right_color);
+ col.set(3, left_color);
+ pos.set(0, Vector2(0, margin));
+ pos.set(1, Vector2(size.x, margin));
+ pos.set(2, Vector2(size.x, margin * 2));
+ pos.set(3, Vector2(0, margin * 2));
+
+ slider->draw_polygon(pos, col);
+ }
+}
+
+bool ColorModeRAW::apply_theme() const {
+ for (int i = 0; i < 4; i++) {
+ HSlider *slider = color_picker->get_slider(i);
+ slider->remove_theme_icon_override("grabber");
+ slider->remove_theme_icon_override("grabber_highlight");
+ slider->remove_theme_style_override("slider");
+ slider->remove_theme_style_override("grabber_area");
+ slider->remove_theme_style_override("grabber_area_highlight");
+ }
+
+ return true;
+}
+
+String ColorModeOKHSL::get_slider_label(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 3, String(), "Couldn't get slider label.");
+ return labels[idx];
+}
+
+float ColorModeOKHSL::get_slider_max(int idx) const {
+ ERR_FAIL_INDEX_V_MSG(idx, 4, 0, "Couldn't get slider max value.");
+ return slider_max[idx];
+}
+
+float ColorModeOKHSL::get_slider_value(int idx) const {
+ switch (idx) {
+ case 0:
+ return color_picker->get_pick_color().get_ok_hsl_h() * 360.0;
+ case 1:
+ return color_picker->get_pick_color().get_ok_hsl_s() * 100.0;
+ case 2:
+ return color_picker->get_pick_color().get_ok_hsl_l() * 100.0;
+ case 3:
+ return Math::round(color_picker->get_pick_color().components[3] * 255.0);
+ default:
+ ERR_FAIL_V_MSG(0, "Couldn't get slider value.");
+ }
+}
+
+Color ColorModeOKHSL::get_color() const {
+ Vector<float> values = color_picker->get_active_slider_values();
+ Color color;
+ color.set_ok_hsl(values[0] / 360.0, values[1] / 100.0, values[2] / 100.0, values[3] / 255.0);
+ return color;
+}
+
+void ColorModeOKHSL::slider_draw(int p_which) {
+ Vector<Vector2> pos;
+ pos.resize(4);
+ Vector<Color> col;
+ col.resize(4);
+ HSlider *slider = color_picker->get_slider(p_which);
+ Size2 size = slider->get_size();
+ Color left_color;
+ Color right_color;
+ Color color = color_picker->get_pick_color();
+ const real_t margin = 4 * color_picker->get_theme_default_base_scale();
+
+ if (p_which == ColorPicker::SLIDER_COUNT) {
+ slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
+
+ left_color = color;
+ left_color.a = 0;
+ right_color = color;
+ right_color.a = 1;
+ } else if (p_which == 0) {
+ Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
+ slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
+ slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true);
+ return;
+ } else {
+ Color s_col;
+ Color v_col;
+ s_col.set_ok_hsl(color.get_h(), 0, color.get_v());
+ left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
+ s_col.set_ok_hsl(color.get_h(), 1, color.get_v());
+ v_col.set_ok_hsl(color.get_h(), color.get_s(), 1);
+ right_color = (p_which == 1) ? s_col : v_col;
+ }
+ col.set(0, left_color);
+ col.set(1, right_color);
+ col.set(2, right_color);
+ col.set(3, left_color);
+ pos.set(0, Vector2(0, margin));
+ pos.set(1, Vector2(size.x, margin));
+ pos.set(2, Vector2(size.x, margin * 2));
+ pos.set(3, Vector2(0, margin * 2));
+
+ slider->draw_polygon(pos, col);
+}
diff --git a/scene/gui/color_mode.h b/scene/gui/color_mode.h
new file mode 100644
index 0000000000..8a19699c40
--- /dev/null
+++ b/scene/gui/color_mode.h
@@ -0,0 +1,143 @@
+/*************************************************************************/
+/* color_mode.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef COLOR_MODE_H
+#define COLOR_MODE_H
+
+#include "scene/gui/color_picker.h"
+
+struct Color;
+
+class ColorMode {
+public:
+ ColorPicker *color_picker = nullptr;
+
+ virtual String get_name() const = 0;
+
+ virtual int get_slider_count() const { return 3; };
+ virtual float get_slider_step() const = 0;
+ virtual String get_slider_label(int idx) const = 0;
+ virtual float get_slider_max(int idx) const = 0;
+ virtual float get_slider_value(int idx) const = 0;
+
+ virtual Color get_color() const = 0;
+
+ virtual void slider_draw(int p_which) = 0;
+ virtual bool apply_theme() const { return false; }
+ virtual ColorPicker::PickerShapeType get_shape_override() const { return ColorPicker::SHAPE_MAX; }
+
+ ColorMode(ColorPicker *p_color_picker);
+ virtual ~ColorMode(){};
+};
+
+class ColorModeHSV : public ColorMode {
+public:
+ String labels[3] = { "H", "S", "V" };
+ float slider_max[4] = { 359, 100, 100, 255 };
+
+ virtual String get_name() const override { return "HSV"; }
+
+ virtual float get_slider_step() const override { return 1.0; }
+ virtual String get_slider_label(int idx) const override;
+ virtual float get_slider_max(int idx) const override;
+ virtual float get_slider_value(int idx) const override;
+
+ virtual Color get_color() const override;
+
+ virtual void slider_draw(int p_which) override;
+
+ ColorModeHSV(ColorPicker *p_color_picker) :
+ ColorMode(p_color_picker){};
+};
+
+class ColorModeRGB : public ColorMode {
+public:
+ String labels[3] = { "R", "G", "B" };
+
+ virtual String get_name() const override { return "RGB"; }
+
+ virtual float get_slider_step() const override { return 1; }
+ virtual String get_slider_label(int idx) const override;
+ virtual float get_slider_max(int idx) const override;
+ virtual float get_slider_value(int idx) const override;
+
+ virtual Color get_color() const override;
+
+ virtual void slider_draw(int p_which) override;
+
+ ColorModeRGB(ColorPicker *p_color_picker) :
+ ColorMode(p_color_picker){};
+};
+
+class ColorModeRAW : public ColorMode {
+public:
+ String labels[3] = { "R", "G", "B" };
+ float slider_max[4] = { 100, 100, 100, 1 };
+
+ virtual String get_name() const override { return "RAW"; }
+
+ virtual float get_slider_step() const override { return 0.01; }
+ virtual String get_slider_label(int idx) const override;
+ virtual float get_slider_max(int idx) const override;
+ virtual float get_slider_value(int idx) const override;
+
+ virtual Color get_color() const override;
+
+ virtual void slider_draw(int p_which) override;
+ virtual bool apply_theme() const override;
+
+ ColorModeRAW(ColorPicker *p_color_picker) :
+ ColorMode(p_color_picker){};
+};
+
+class ColorModeOKHSL : public ColorMode {
+public:
+ String labels[3] = { "H", "S", "L" };
+ float slider_max[4] = { 359, 100, 100, 255 };
+
+ virtual String get_name() const override { return "OKHSL"; }
+
+ virtual float get_slider_step() const override { return 1.0; }
+ virtual String get_slider_label(int idx) const override;
+ virtual float get_slider_max(int idx) const override;
+ virtual float get_slider_value(int idx) const override;
+
+ virtual Color get_color() const override;
+
+ virtual void slider_draw(int p_which) override;
+ virtual ColorPicker::PickerShapeType get_shape_override() const override { return ColorPicker::SHAPE_OKHSL_CIRCLE; }
+
+ ColorModeOKHSL(ColorPicker *p_color_picker) :
+ ColorMode(p_color_picker){};
+
+ ~ColorModeOKHSL(){};
+};
+
+#endif // COLOR_MODE_H
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 28d645e8f6..492a81f933 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -34,7 +34,7 @@
#include "core/math/color.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
-#include "scene/main/window.h"
+#include "scene/gui/color_mode.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
@@ -75,10 +75,14 @@ void ColorPicker::_notification(int p_what) {
wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));
wheel_margin->add_theme_constant_override("margin_bottom", 8 * get_theme_default_base_scale());
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < SLIDER_COUNT; i++) {
labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin")));
}
+ alpha_label->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
+ set_offset((Side)0, get_offset((Side)0) + get_theme_constant(SNAME("margin")));
+
+ _reset_theme();
if (Engine::get_singleton()->is_editor_hint()) {
// Adjust for the width of the "Script" icon.
@@ -194,75 +198,38 @@ void ColorPicker::set_focus_on_line_edit() {
}
void ColorPicker::_update_controls() {
- const char *rgb[3] = { "R", "G", "B" };
- const char *hsv[3] = { "H", "S", "V" };
- const char *hsl[3] = { "H", "S", "L" };
- if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
- for (int i = 0; i < 3; i++) {
- labels[i]->set_text(hsl[i]);
- }
- } else if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
- for (int i = 0; i < 3; i++) {
- labels[i]->set_text(hsv[i]);
- }
- } else {
- for (int i = 0; i < 3; i++) {
- labels[i]->set_text(rgb[i]);
- }
+ int mode_sliders_count = modes[current_mode]->get_slider_count();
+
+ for (int i = current_slider_count; i < mode_sliders_count; i++) {
+ sliders[i]->show();
+ labels[i]->show();
+ values[i]->show();
}
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
- btn_hsv->set_text(RTR("OKHSL"));
- } else {
- btn_hsv->set_text(RTR("HSV"));
- }
- if (hsv_mode_enabled) {
- set_raw_mode(false);
- set_hsv_mode(true);
- btn_raw->set_disabled(true);
- } else if (raw_mode_enabled) {
- set_raw_mode(true);
- set_hsv_mode(false);
- btn_raw->set_disabled(false);
- btn_hsv->set_disabled(true);
- } else {
- set_raw_mode(false);
- set_hsv_mode(false);
- btn_raw->set_disabled(false);
- btn_hsv->set_disabled(false);
- }
-
- if (raw_mode_enabled) {
- for (int i = 0; i < 3; i++) {
- scroll[i]->remove_theme_icon_override("grabber");
- scroll[i]->remove_theme_icon_override("grabber_highlight");
- scroll[i]->remove_theme_style_override("slider");
- scroll[i]->remove_theme_style_override("grabber_area");
- scroll[i]->remove_theme_style_override("grabber_area_highlight");
- }
- } else {
- Ref<StyleBoxEmpty> style_box_empty(memnew(StyleBoxEmpty));
- Ref<Texture2D> bar_arrow = get_theme_icon(SNAME("bar_arrow"));
-
- for (int i = 0; i < 4; i++) {
- scroll[i]->add_theme_icon_override("grabber", bar_arrow);
- scroll[i]->add_theme_icon_override("grabber_highlight", bar_arrow);
- scroll[i]->add_theme_style_override("slider", style_box_empty);
- scroll[i]->add_theme_style_override("grabber_area", style_box_empty);
- scroll[i]->add_theme_style_override("grabber_area_highlight", style_box_empty);
- }
+ for (int i = mode_sliders_count; i < current_slider_count; i++) {
+ sliders[i]->hide();
+ labels[i]->hide();
+ values[i]->hide();
}
+ current_slider_count = mode_sliders_count;
+
+ for (int i = 0; i < current_slider_count; i++) {
+ labels[i]->set_text(modes[current_mode]->get_slider_label(i));
+ }
+ alpha_label->set_text("A");
+
+ slider_theme_modified = modes[current_mode]->apply_theme();
if (edit_alpha) {
- values[3]->show();
- scroll[3]->show();
- labels[3]->show();
+ alpha_value->show();
+ alpha_slider->show();
+ alpha_label->show();
} else {
- values[3]->hide();
- scroll[3]->hide();
- labels[3]->hide();
+ alpha_value->hide();
+ alpha_slider->hide();
+ alpha_label->hide();
}
- switch (picker_type) {
+ switch (_get_actual_shape()) {
case SHAPE_HSV_RECTANGLE:
wheel_edit->hide();
w_edit->show();
@@ -297,7 +264,7 @@ void ColorPicker::_update_controls() {
void ColorPicker::_set_pick_color(const Color &p_color, bool p_update_sliders) {
color = p_color;
if (color != last_color) {
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (_get_actual_shape() == SHAPE_OKHSL_CIRCLE) {
h = color.get_ok_hsl_h();
s = color.get_ok_hsl_s();
v = color.get_ok_hsl_l();
@@ -353,27 +320,93 @@ void ColorPicker::_value_changed(double) {
return;
}
- if (hsv_mode_enabled) {
- h = scroll[0]->get_value() / 360.0;
- s = scroll[1]->get_value() / 100.0;
- v = scroll[2]->get_value() / 100.0;
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
- color.set_ok_hsl(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
- } else {
- color.set_hsv(h, s, v, Math::round(scroll[3]->get_value() / 255.0));
- }
+ color = modes[current_mode]->get_color();
+ if (current_mode == MODE_HSV || current_mode == MODE_OKHSL) {
+ h = sliders[0]->get_value() / 360.0;
+ s = sliders[1]->get_value() / 100.0;
+ v = sliders[2]->get_value() / 100.0;
last_color = color;
- } else {
- for (int i = 0; i < 4; i++) {
- color.components[i] = scroll[i]->get_value() / (raw_mode_enabled ? 1.0 : 255.0);
- }
}
_set_pick_color(color, false);
emit_signal(SNAME("color_changed"), color);
}
+void ColorPicker::add_mode(ColorMode *p_mode) {
+ modes.push_back(p_mode);
+ mode_option_button->add_item(RTR(p_mode->get_name()));
+}
+
+void ColorPicker::create_slider(GridContainer *gc, int idx) {
+ Label *l = memnew(Label());
+ l->set_v_size_flags(SIZE_SHRINK_CENTER);
+ gc->add_child(l);
+
+ HSlider *s = memnew(HSlider);
+ s->set_v_size_flags(SIZE_SHRINK_CENTER);
+ s->set_focus_mode(FOCUS_NONE);
+ gc->add_child(s);
+
+ SpinBox *v = memnew(SpinBox);
+ s->share(v);
+ gc->add_child(v);
+ v->get_line_edit()->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
+ v->get_line_edit()->connect("focus_exited", callable_mp(this, &ColorPicker::_focus_exit));
+
+ s->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ s->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed));
+ s->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(idx));
+
+ if (idx < SLIDER_COUNT) {
+ sliders[idx] = s;
+ values[idx] = v;
+ labels[idx] = l;
+ } else {
+ alpha_slider = s;
+ alpha_value = v;
+ alpha_label = l;
+ }
+}
+
+HSlider *ColorPicker::get_slider(int idx) {
+ if (idx < SLIDER_COUNT) {
+ return sliders[idx];
+ }
+ return alpha_slider;
+}
+
+Vector<float> ColorPicker::get_active_slider_values() {
+ Vector<float> values;
+ for (int i = 0; i < current_slider_count; i++) {
+ values.push_back(sliders[i]->get_value());
+ }
+ values.push_back(alpha_slider->get_value());
+ return values;
+}
+
+ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const {
+ return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape;
+}
+
+void ColorPicker::_reset_theme() {
+ Ref<StyleBoxEmpty> style_box_empty(memnew(StyleBoxEmpty));
+
+ for (int i = 0; i < SLIDER_COUNT; i++) {
+ sliders[i]->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
+ sliders[i]->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
+ sliders[i]->add_theme_style_override("slider", style_box_empty);
+ sliders[i]->add_theme_style_override("grabber_area", style_box_empty);
+ sliders[i]->add_theme_style_override("grabber_area_highlight", style_box_empty);
+ }
+ alpha_slider->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
+ alpha_slider->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker")));
+ alpha_slider->add_theme_style_override("slider", style_box_empty);
+ alpha_slider->add_theme_style_override("grabber_area", style_box_empty);
+ alpha_slider->add_theme_style_override("grabber_area_highlight", style_box_empty);
+}
+
void ColorPicker::_html_submitted(const String &p_html) {
if (updating || text_is_constructor || !c_text->is_visible()) {
return;
@@ -397,35 +430,15 @@ void ColorPicker::_update_color(bool p_update_sliders) {
updating = true;
if (p_update_sliders) {
- if (hsv_mode_enabled) {
- for (int i = 0; i < 4; i++) {
- scroll[i]->set_step(1.0);
- }
- scroll[0]->set_max(359);
- scroll[0]->set_value(h * 360.0);
- scroll[1]->set_max(100);
- scroll[1]->set_value(s * 100.0);
- scroll[2]->set_max(100);
- scroll[2]->set_value(v * 100.0);
- scroll[3]->set_max(255);
- scroll[3]->set_value(Math::round(color.components[3] * 255.0));
- } else {
- for (int i = 0; i < 4; i++) {
- if (raw_mode_enabled) {
- scroll[i]->set_step(0.01);
- scroll[i]->set_max(100);
- if (i == 3) {
- scroll[i]->set_max(1);
- }
- scroll[i]->set_value(color.components[i]);
- } else {
- scroll[i]->set_step(1);
- const float byte_value = Math::round(color.components[i] * 255.0);
- scroll[i]->set_max(next_power_of_2(MAX(255, byte_value)) - 1);
- scroll[i]->set_value(byte_value);
- }
- }
+ float step = modes[current_mode]->get_slider_step();
+ for (int i = 0; i < current_slider_count; i++) {
+ sliders[i]->set_max(modes[current_mode]->get_slider_max(i));
+ sliders[i]->set_step(step);
+ sliders[i]->set_value(modes[current_mode]->get_slider_value(i));
}
+ alpha_slider->set_max(modes[current_mode]->get_slider_max(current_slider_count));
+ alpha_slider->set_step(step);
+ alpha_slider->set_value(modes[current_mode]->get_slider_value(current_slider_count));
}
_update_text_value();
@@ -433,9 +446,10 @@ void ColorPicker::_update_color(bool p_update_sliders) {
sample->update();
uv_edit->update();
w_edit->update();
- for (int i = 0; i < 4; i++) {
- scroll[i]->update();
+ for (int i = 0; i < current_slider_count; i++) {
+ sliders[i]->update();
}
+ alpha_slider->update();
wheel->update();
wheel_uv->update();
updating = false;
@@ -481,15 +495,16 @@ Color ColorPicker::get_pick_color() const {
return color;
}
-void ColorPicker::set_picker_shape(PickerShapeType p_picker_type) {
- ERR_FAIL_INDEX(p_picker_type, SHAPE_MAX);
- picker_type = p_picker_type;
+void ColorPicker::set_picker_shape(PickerShapeType p_shape) {
+ ERR_FAIL_INDEX(p_shape, SHAPE_MAX);
+ current_shape = p_shape;
+
_update_controls();
_update_color();
}
ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const {
- return picker_type;
+ return current_shape;
}
inline int ColorPicker::_get_preset_size() {
@@ -505,6 +520,21 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
preset_container->add_child(btn_preset);
}
+void ColorPicker::_set_color_mode(ColorModeType p_mode) {
+ if (slider_theme_modified) {
+ _reset_theme();
+ }
+
+ current_mode = p_mode;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ _update_controls();
+ _update_color();
+}
+
void ColorPicker::add_preset(const Color &p_color) {
if (presets.find(p_color)) {
presets.move_to_back(presets.find(p_color));
@@ -564,46 +594,14 @@ PackedColorArray ColorPicker::get_presets() const {
return arr;
}
-void ColorPicker::set_hsv_mode(bool p_enabled) {
- if (hsv_mode_enabled == p_enabled || raw_mode_enabled) {
- return;
- }
- hsv_mode_enabled = p_enabled;
- if (btn_hsv->is_pressed() != p_enabled) {
- btn_hsv->set_pressed(p_enabled);
- }
-
- if (!is_inside_tree()) {
- return;
- }
-
- _update_controls();
- _update_color();
-}
-
-bool ColorPicker::is_hsv_mode() const {
- return hsv_mode_enabled;
-}
-
-void ColorPicker::set_raw_mode(bool p_enabled) {
- if (raw_mode_enabled == p_enabled || hsv_mode_enabled) {
- return;
- }
- raw_mode_enabled = p_enabled;
- if (btn_raw->is_pressed() != p_enabled) {
- btn_raw->set_pressed(p_enabled);
- }
-
- if (!is_inside_tree()) {
- return;
- }
-
- _update_controls();
- _update_color();
+void ColorPicker::set_color_mode(ColorModeType p_mode) {
+ ERR_FAIL_INDEX(p_mode, MODE_MAX);
+ mode_option_button->select(p_mode);
+ _set_color_mode(p_mode);
}
-bool ColorPicker::is_raw_mode() const {
- return raw_mode_enabled;
+ColorPicker::ColorModeType ColorPicker::get_color_mode() const {
+ return current_mode;
}
void ColorPicker::set_deferred_mode(bool p_enabled) {
@@ -690,6 +688,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
if (!c) {
return;
}
+
+ PickerShapeType actual_shape = _get_actual_shape();
if (p_which == 0) {
Vector<Point2> points;
Vector<Color> colors;
@@ -697,7 +697,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
Color col = color;
Vector2 center = c->get_size() / 2.0;
- switch (picker_type) {
+ switch (actual_shape) {
case SHAPE_HSV_WHEEL: {
points.resize(4);
colors.resize(4);
@@ -759,7 +759,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
Ref<Texture2D> cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker"));
int x;
int y;
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2);
y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2);
} else {
@@ -773,7 +773,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
c->draw_texture(cursor, Point2(x, y));
col.set_hsv(h, 1, 1);
- if (picker_type == SHAPE_HSV_WHEEL) {
+ if (actual_shape == SHAPE_HSV_WHEEL) {
points.resize(4);
double h1 = h - (0.5 / 360);
double h2 = h + (0.5 / 360);
@@ -785,14 +785,14 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
}
} else if (p_which == 1) {
- if (picker_type == SHAPE_HSV_RECTANGLE) {
+ if (actual_shape == SHAPE_HSV_RECTANGLE) {
Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col;
col.set_hsv(h, 1, 1);
c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
- } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ } else if (actual_shape == SHAPE_OKHSL_CIRCLE) {
Vector<Point2> points;
Vector<Color> colors;
Color col;
@@ -811,7 +811,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
int y = c->get_size().y - c->get_size().y * CLAMP(v, 0, 1);
col.set_ok_hsl(h, 1, v);
c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
- } else if (picker_type == SHAPE_VHS_CIRCLE) {
+ } else if (actual_shape == SHAPE_VHS_CIRCLE) {
Vector<Point2> points;
Vector<Color> colors;
Color col;
@@ -833,87 +833,24 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
}
} else if (p_which == 2) {
c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1));
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
circle_mat->set_shader_param("v", v);
}
}
}
void ColorPicker::_slider_draw(int p_which) {
- Vector<Vector2> pos;
- pos.resize(4);
- Vector<Color> col;
- col.resize(4);
- Size2 size = scroll[p_which]->get_size();
- Color left_color;
- Color right_color;
- const real_t margin = 4 * get_theme_default_base_scale();
-
- if (p_which == 3) {
- scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true);
-
- left_color = color;
- left_color.a = 0;
- right_color = color;
- right_color.a = 1;
- } else {
- if (raw_mode_enabled) {
- return;
- }
- if (hsv_mode_enabled) {
- if (p_which == 0) {
- Ref<Texture2D> hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
- scroll[p_which]->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
- scroll[p_which]->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(scroll[p_which]->get_size().x, margin)), false, Color(1, 1, 1), true);
- return;
- }
- Color s_col;
- Color v_col;
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
- s_col.set_ok_hsl(h, 0, v);
- } else {
- s_col.set_hsv(h, 0, v);
- }
- left_color = (p_which == 1) ? s_col : Color(0, 0, 0);
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
- s_col.set_ok_hsl(h, 1, v);
- v_col.set_ok_hsl(h, s, 1);
- } else {
- s_col.set_hsv(h, 1, v);
- v_col.set_hsv(h, s, 1);
- }
- right_color = (p_which == 1) ? s_col : v_col;
- } else {
- left_color = Color(
- p_which == 0 ? 0 : color.r,
- p_which == 1 ? 0 : color.g,
- p_which == 2 ? 0 : color.b);
- right_color = Color(
- p_which == 0 ? 1 : color.r,
- p_which == 1 ? 1 : color.g,
- p_which == 2 ? 1 : color.b);
- }
- }
-
- col.set(0, left_color);
- col.set(1, right_color);
- col.set(2, right_color);
- col.set(3, left_color);
- pos.set(0, Vector2(0, margin));
- pos.set(1, Vector2(size.x, margin));
- pos.set(2, Vector2(size.x, margin * 2));
- pos.set(3, Vector2(0, margin * 2));
-
- scroll[p_which]->draw_polygon(pos, col);
+ modes[current_mode]->slider_draw(p_which);
}
void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
Ref<InputEventMouseButton> bev = p_event;
+ PickerShapeType current_picker = _get_actual_shape();
if (bev.is_valid()) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (current_picker == SHAPE_VHS_CIRCLE || current_picker == SHAPE_OKHSL_CIRCLE) {
real_t dist = center.distance_to(bev->get_position());
if (dist <= center.x) {
real_t rad = center.angle_to_point(bev->get_position());
@@ -951,11 +888,12 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
}
changing_color = true;
- if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (current_picker == SHAPE_OKHSL_CIRCLE) {
color.set_ok_hsl(h, s, v, color.a);
- } else if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ } else {
color.set_hsv(h, s, v, color.a);
}
+
last_color = color;
set_pick_color(color);
@@ -981,7 +919,7 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
}
Vector2 center = c->get_size() / 2.0;
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (current_picker == SHAPE_VHS_CIRCLE || current_picker == SHAPE_OKHSL_CIRCLE) {
real_t dist = center.distance_to(mev->get_position());
real_t rad = center.angle_to_point(mev->get_position());
h = ((rad >= 0) ? rad : (Math_TAU + rad)) / Math_TAU;
@@ -1002,9 +940,9 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
v = 1.0 - (y - corner_y) / real_size.y;
}
}
- if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ if (current_picker != SHAPE_OKHSL_CIRCLE) {
color.set_hsv(h, s, v, color.a);
- } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ } else {
color.set_ok_hsl(h, s, v, color.a);
}
last_color = color;
@@ -1018,12 +956,13 @@ void ColorPicker::_uv_input(const Ref<InputEvent> &p_event, Control *c) {
void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> bev = p_event;
+ PickerShapeType actual_shape = _get_actual_shape();
if (bev.is_valid()) {
if (bev->is_pressed() && bev->get_button_index() == MouseButton::LEFT) {
changing_color = true;
float y = CLAMP((float)bev->get_position().y, 0, w_edit->get_size().height);
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
@@ -1031,9 +970,9 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
} else {
changing_color = false;
}
- if (picker_type != SHAPE_OKHSL_CIRCLE) {
+ if (actual_shape != SHAPE_OKHSL_CIRCLE) {
color.set_hsv(h, s, v, color.a);
- } else if (picker_type == SHAPE_OKHSL_CIRCLE) {
+ } else {
color.set_ok_hsl(h, s, v, color.a);
}
last_color = color;
@@ -1053,16 +992,18 @@ void ColorPicker::_w_input(const Ref<InputEvent> &p_event) {
return;
}
float y = CLAMP((float)mev->get_position().y, 0, w_edit->get_size().height);
- if (picker_type == SHAPE_VHS_CIRCLE || picker_type == SHAPE_OKHSL_CIRCLE) {
+ if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
v = 1.0 - (y / w_edit->get_size().height);
} else {
h = y / w_edit->get_size().height;
}
- if (hsv_mode_enabled && picker_type != SHAPE_OKHSL_CIRCLE) {
+
+ if (current_mode == MODE_HSV) {
color.set_hsv(h, s, v, color.a);
- } else if (hsv_mode_enabled && picker_type == SHAPE_OKHSL_CIRCLE) {
+ } else if (current_mode == MODE_OKHSL) {
color.set_ok_hsl(h, s, v, color.a);
}
+
last_color = color;
set_pick_color(color);
_update_color();
@@ -1153,21 +1094,30 @@ void ColorPicker::_focus_enter() {
c_text->select(0, 0);
}
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < current_slider_count; i++) {
if (values[i]->get_line_edit()->has_focus() && !has_ctext_focus) {
values[i]->get_line_edit()->select_all();
} else {
values[i]->get_line_edit()->select(0, 0);
}
}
+ if (alpha_value->get_line_edit()->has_focus() && !has_ctext_focus) {
+ alpha_value->get_line_edit()->select_all();
+ } else {
+ alpha_value->get_line_edit()->select(0, 0);
+ }
}
void ColorPicker::_focus_exit() {
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < current_slider_count; i++) {
if (!values[i]->get_line_edit()->get_menu()->is_visible()) {
values[i]->get_line_edit()->select(0, 0);
}
}
+ if (!alpha_value->get_line_edit()->get_menu()->is_visible()) {
+ alpha_value->get_line_edit()->select(0, 0);
+ }
+
c_text->select(0, 0);
}
@@ -1207,12 +1157,10 @@ bool ColorPicker::are_presets_visible() const {
void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color);
ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPicker::get_pick_color);
- ClassDB::bind_method(D_METHOD("set_hsv_mode", "enabled"), &ColorPicker::set_hsv_mode);
- ClassDB::bind_method(D_METHOD("is_hsv_mode"), &ColorPicker::is_hsv_mode);
- ClassDB::bind_method(D_METHOD("set_raw_mode", "enabled"), &ColorPicker::set_raw_mode);
- ClassDB::bind_method(D_METHOD("is_raw_mode"), &ColorPicker::is_raw_mode);
ClassDB::bind_method(D_METHOD("set_deferred_mode", "mode"), &ColorPicker::set_deferred_mode);
ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode);
+ ClassDB::bind_method(D_METHOD("set_color_mode", "color_mode"), &ColorPicker::set_color_mode);
+ ClassDB::bind_method(D_METHOD("get_color_mode"), &ColorPicker::get_color_mode);
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha);
ClassDB::bind_method(D_METHOD("set_presets_enabled", "enabled"), &ColorPicker::set_presets_enabled);
@@ -1222,13 +1170,12 @@ void ColorPicker::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset);
ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset);
ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets);
- ClassDB::bind_method(D_METHOD("set_picker_shape", "picker"), &ColorPicker::set_picker_shape);
+ ClassDB::bind_method(D_METHOD("set_picker_shape", "shape"), &ColorPicker::set_picker_shape);
ClassDB::bind_method(D_METHOD("get_picker_shape"), &ColorPicker::get_picker_shape);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hsv_mode"), "set_hsv_mode", "is_hsv_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "color_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW,OKHSL"), "set_color_mode", "get_color_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle,OKHSL Circle"), "set_picker_shape", "get_picker_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled");
@@ -1238,6 +1185,11 @@ void ColorPicker::_bind_methods() {
ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color")));
ADD_SIGNAL(MethodInfo("preset_removed", PropertyInfo(Variant::COLOR, "color")));
+ BIND_ENUM_CONSTANT(MODE_RGB);
+ BIND_ENUM_CONSTANT(MODE_HSV);
+ BIND_ENUM_CONSTANT(MODE_RAW);
+ BIND_ENUM_CONSTANT(MODE_OKHSL);
+
BIND_ENUM_CONSTANT(SHAPE_HSV_RECTANGLE);
BIND_ENUM_CONSTANT(SHAPE_HSV_WHEEL);
BIND_ENUM_CONSTANT(SHAPE_VHS_CIRCLE);
@@ -1250,6 +1202,7 @@ ColorPicker::ColorPicker() :
add_child(hb_edit, false, INTERNAL_MODE_FRONT);
hb_edit->set_v_size_flags(SIZE_EXPAND_FILL);
+ uv_edit = memnew(Control);
hb_edit->add_child(uv_edit);
uv_edit->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(uv_edit));
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
@@ -1260,11 +1213,13 @@ ColorPicker::ColorPicker() :
HBoxContainer *hb_smpl = memnew(HBoxContainer);
add_child(hb_smpl, false, INTERNAL_MODE_FRONT);
+ sample = memnew(TextureRect);
hb_smpl->add_child(sample);
sample->set_h_size_flags(SIZE_EXPAND_FILL);
sample->connect("gui_input", callable_mp(this, &ColorPicker::_sample_input));
sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw));
+ btn_pick = memnew(Button);
btn_pick->set_flat(true);
hb_smpl->add_child(btn_pick);
btn_pick->set_toggle_mode(true);
@@ -1277,51 +1232,35 @@ ColorPicker::ColorPicker() :
add_child(memnew(HSeparator), false, INTERNAL_MODE_FRONT);
VBoxContainer *vbr = memnew(VBoxContainer);
+
add_child(vbr, false, INTERNAL_MODE_FRONT);
vbr->set_h_size_flags(SIZE_EXPAND_FILL);
- for (int i = 0; i < 4; i++) {
- HBoxContainer *hbc = memnew(HBoxContainer);
+ GridContainer *gc = memnew(GridContainer);
- labels[i] = memnew(Label());
- labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));
- labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
- hbc->add_child(labels[i]);
+ vbr->add_child(gc);
+ gc->set_h_size_flags(SIZE_EXPAND_FILL);
+ gc->set_columns(3);
- scroll[i] = memnew(HSlider);
- scroll[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
- scroll[i]->set_focus_mode(FOCUS_NONE);
- hbc->add_child(scroll[i]);
-
- values[i] = memnew(SpinBox);
- scroll[i]->share(values[i]);
- hbc->add_child(values[i]);
- values[i]->get_line_edit()->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
- values[i]->get_line_edit()->connect("focus_exited", callable_mp(this, &ColorPicker::_focus_exit));
-
- scroll[i]->set_min(0);
- scroll[i]->set_page(0);
- scroll[i]->set_h_size_flags(SIZE_EXPAND_FILL);
-
- scroll[i]->connect("value_changed", callable_mp(this, &ColorPicker::_value_changed));
- scroll[i]->connect("draw", callable_mp(this, &ColorPicker::_slider_draw), make_binds(i));
-
- vbr->add_child(hbc);
+ for (int i = 0; i < SLIDER_COUNT + 1; i++) {
+ create_slider(gc, i);
}
- labels[3]->set_text("A");
+ alpha_label->set_text("A");
HBoxContainer *hhb = memnew(HBoxContainer);
vbr->add_child(hhb);
- hhb->add_child(btn_hsv);
- btn_hsv->set_text(RTR("HSV"));
- btn_hsv->connect("toggled", callable_mp(this, &ColorPicker::set_hsv_mode));
+ mode_option_button = memnew(OptionButton);
- hhb->add_child(btn_raw);
- btn_raw->set_text(RTR("Raw"));
- btn_raw->connect("toggled", callable_mp(this, &ColorPicker::set_raw_mode));
+ hhb->add_child(mode_option_button);
+ add_mode(new ColorModeRGB(this));
+ add_mode(new ColorModeHSV(this));
+ add_mode(new ColorModeRAW(this));
+ add_mode(new ColorModeOKHSL(this));
+ mode_option_button->connect("item_selected", callable_mp(this, &ColorPicker::_set_color_mode));
+ text_type = memnew(Button);
hhb->add_child(text_type);
text_type->set_text("#");
text_type->set_tooltip(RTR("Switch between hexadecimal and code values."));
@@ -1332,12 +1271,14 @@ ColorPicker::ColorPicker() :
text_type->set_mouse_filter(MOUSE_FILTER_IGNORE);
}
+ c_text = memnew(LineEdit);
hhb->add_child(c_text);
c_text->set_h_size_flags(SIZE_EXPAND_FILL);
c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
c_text->connect("focus_entered", callable_mp(this, &ColorPicker::_focus_enter));
c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit));
+ wheel_edit = memnew(AspectRatioContainer);
wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL);
wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL);
hb_edit->add_child(wheel_edit);
@@ -1347,41 +1288,53 @@ ColorPicker::ColorPicker() :
circle_mat.instantiate();
circle_mat->set_shader(circle_shader);
+ wheel_margin = memnew(MarginContainer);
wheel_margin->add_theme_constant_override("margin_bottom", 8);
wheel_edit->add_child(wheel_margin);
+ wheel = memnew(Control);
wheel_margin->add_child(wheel);
wheel->set_mouse_filter(MOUSE_FILTER_PASS);
wheel->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(2, wheel));
+ wheel_uv = memnew(Control);
wheel_margin->add_child(wheel_uv);
wheel_uv->connect("gui_input", callable_mp(this, &ColorPicker::_uv_input), make_binds(wheel_uv));
wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv));
+ w_edit = memnew(Control);
hb_edit->add_child(w_edit);
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input));
w_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(1, w_edit));
- picker_type = SHAPE_HSV_RECTANGLE;
_update_controls();
updating = false;
set_pick_color(Color(1, 1, 1));
+ preset_separator = memnew(HSeparator);
add_child(preset_separator, false, INTERNAL_MODE_FRONT);
+ preset_container = memnew(GridContainer);
preset_container->set_h_size_flags(SIZE_EXPAND_FILL);
preset_container->set_columns(preset_column_count);
add_child(preset_container, false, INTERNAL_MODE_FRONT);
+ btn_add_preset = memnew(Button);
btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
btn_add_preset->set_tooltip(RTR("Add current color as a preset."));
btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
preset_container->add_child(btn_add_preset);
}
+ColorPicker::~ColorPicker() {
+ for (int i = 0; i < modes.size(); i++) {
+ delete modes[i];
+ }
+}
+
/////////////////
void ColorPickerButton::_about_to_popup() {
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 953be032ec..e219c78319 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -34,16 +34,23 @@
#include "scene/gui/aspect_ratio_container.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
-#include "scene/gui/check_button.h"
+#include "scene/gui/control.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
+#include "scene/gui/option_button.h"
#include "scene/gui/popup.h"
#include "scene/gui/separator.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/texture_rect.h"
+class ColorMode;
+class ColorModeRGB;
+class ColorModeHSV;
+class ColorModeRAW;
+class ColorModeOKHSL;
+
class ColorPresetButton : public BaseButton {
GDCLASS(ColorPresetButton, BaseButton);
@@ -64,6 +71,15 @@ class ColorPicker : public BoxContainer {
GDCLASS(ColorPicker, BoxContainer);
public:
+ enum ColorModeType {
+ MODE_RGB,
+ MODE_HSV,
+ MODE_RAW,
+ MODE_OKHSL,
+
+ MODE_MAX
+ };
+
enum PickerShapeType {
SHAPE_HSV_RECTANGLE,
SHAPE_HSV_WHEEL,
@@ -73,38 +89,52 @@ public:
SHAPE_MAX
};
+ static const int SLIDER_COUNT = 4;
+
private:
static Ref<Shader> wheel_shader;
static Ref<Shader> circle_shader;
static Ref<Shader> circle_ok_color_shader;
static List<Color> preset_cache;
+ int current_slider_count = SLIDER_COUNT;
+
+ bool slider_theme_modified = true;
+
+ Vector<ColorMode *> modes;
+
Control *screen = nullptr;
- Control *uv_edit = memnew(Control);
- Control *w_edit = memnew(Control);
- AspectRatioContainer *wheel_edit = memnew(AspectRatioContainer);
- MarginContainer *wheel_margin = memnew(MarginContainer);
+ Control *uv_edit = nullptr;
+ Control *w_edit = nullptr;
+ AspectRatioContainer *wheel_edit = nullptr;
+ MarginContainer *wheel_margin = nullptr;
Ref<ShaderMaterial> wheel_mat;
Ref<ShaderMaterial> circle_mat;
- Control *wheel = memnew(Control);
- Control *wheel_uv = memnew(Control);
- TextureRect *sample = memnew(TextureRect);
- GridContainer *preset_container = memnew(GridContainer);
- HSeparator *preset_separator = memnew(HSeparator);
- Button *btn_add_preset = memnew(Button);
- Button *btn_pick = memnew(Button);
- CheckButton *btn_hsv = memnew(CheckButton);
- CheckButton *btn_raw = memnew(CheckButton);
- HSlider *scroll[4];
- SpinBox *values[4];
- Label *labels[4];
- Button *text_type = memnew(Button);
- LineEdit *c_text = memnew(LineEdit);
+ Control *wheel = nullptr;
+ Control *wheel_uv = nullptr;
+ TextureRect *sample = nullptr;
+ GridContainer *preset_container = nullptr;
+ HSeparator *preset_separator = nullptr;
+ Button *btn_add_preset = nullptr;
+ Button *btn_pick = nullptr;
+
+ OptionButton *mode_option_button = nullptr;
+
+ HSlider *sliders[SLIDER_COUNT];
+ SpinBox *values[SLIDER_COUNT];
+ Label *labels[SLIDER_COUNT];
+ Button *text_type = nullptr;
+ LineEdit *c_text = nullptr;
+
+ HSlider *alpha_slider = nullptr;
+ SpinBox *alpha_value = nullptr;
+ Label *alpha_label = nullptr;
bool edit_alpha = true;
Size2i ms;
bool text_is_constructor = false;
- PickerShapeType picker_type = SHAPE_HSV_WHEEL;
+ PickerShapeType current_shape = SHAPE_HSV_RECTANGLE;
+ ColorModeType current_mode = MODE_RGB;
const int preset_column_count = 9;
int prev_preset_size = 0;
@@ -114,8 +144,6 @@ private:
Color old_color;
bool display_old_color = false;
- bool raw_mode_enabled = false;
- bool hsv_mode_enabled = false;
bool deferred_mode_enabled = false;
bool updating = true;
bool changing_color = false;
@@ -128,6 +156,9 @@ private:
float v = 0.0;
Color last_color;
+ PickerShapeType _get_actual_shape() const;
+ void create_slider(GridContainer *gc, int idx);
+ void _reset_theme();
void _html_submitted(const String &p_html);
void _value_changed(double);
void _update_controls();
@@ -152,14 +183,21 @@ private:
inline int _get_preset_size();
void _add_preset_button(int p_size, const Color &p_color);
+ void _set_color_mode(ColorModeType p_mode);
+
protected:
void _notification(int);
static void _bind_methods();
public:
+ HSlider *get_slider(int idx);
+ Vector<float> get_active_slider_values();
+
static void init_shaders();
static void finish_shaders();
+ void add_mode(ColorMode *p_mode);
+
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
@@ -173,7 +211,7 @@ public:
void set_display_old_color(bool p_enabled);
bool is_displaying_old_color() const;
- void set_picker_shape(PickerShapeType p_picker_type);
+ void set_picker_shape(PickerShapeType p_shape);
PickerShapeType get_picker_shape() const;
void add_preset(const Color &p_color);
@@ -181,11 +219,8 @@ public:
PackedColorArray get_presets() const;
void _update_presets();
- void set_hsv_mode(bool p_enabled);
- bool is_hsv_mode() const;
-
- void set_raw_mode(bool p_enabled);
- bool is_raw_mode() const;
+ void set_color_mode(ColorModeType p_mode);
+ ColorModeType get_color_mode() const;
void set_deferred_mode(bool p_enabled);
bool is_deferred_mode() const;
@@ -199,6 +234,7 @@ public:
void set_focus_on_line_edit();
ColorPicker();
+ ~ColorPicker();
};
class ColorPickerButton : public Button {
@@ -239,4 +275,5 @@ public:
};
VARIANT_ENUM_CAST(ColorPicker::PickerShapeType);
+VARIANT_ENUM_CAST(ColorPicker::ColorModeType);
#endif // COLOR_PICKER_H
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 6e2db68db0..15ff1d3ed6 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1115,7 +1115,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 && (*font)->get_data_count() > 0) {
+ if (font) {
return *font;
}
}
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 0e0f8bde83..6bb4ac9c6f 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -170,7 +170,11 @@ Vector<String> FileDialog::get_selected_files() const {
};
void FileDialog::update_dir() {
- dir->set_text(dir_access->get_current_dir(false));
+ if (root_prefix.is_empty()) {
+ dir->set_text(dir_access->get_current_dir(false));
+ } else {
+ dir->set_text(dir_access->get_current_dir(false).trim_prefix(root_prefix).trim_prefix("/"));
+ }
if (drives->is_visible()) {
if (dir_access->get_current_dir().is_network_share_path()) {
@@ -188,10 +192,8 @@ void FileDialog::update_dir() {
}
void FileDialog::_dir_submitted(String p_dir) {
- dir_access->change_dir(p_dir);
+ _change_dir(root_prefix.plus_file(p_dir));
file->set_text("");
- invalidate();
- update_dir();
_push_history();
}
@@ -378,9 +380,7 @@ bool FileDialog::_is_open_should_be_disabled() {
}
void FileDialog::_go_up() {
- dir_access->change_dir("..");
- update_file_list();
- update_dir();
+ _change_dir("..");
_push_history();
}
@@ -390,9 +390,7 @@ void FileDialog::_go_back() {
}
local_history_pos--;
- dir_access->change_dir(local_history[local_history_pos]);
- update_file_list();
- update_dir();
+ _change_dir(local_history[local_history_pos]);
dir_prev->set_disabled(local_history_pos == 0);
dir_next->set_disabled(local_history_pos == local_history.size() - 1);
@@ -404,9 +402,7 @@ void FileDialog::_go_forward() {
}
local_history_pos++;
- dir_access->change_dir(local_history[local_history_pos]);
- update_file_list();
- update_dir();
+ _change_dir(local_history[local_history_pos]);
dir_prev->set_disabled(local_history_pos == 0);
dir_next->set_disabled(local_history_pos == local_history.size() - 1);
@@ -465,12 +461,10 @@ void FileDialog::_tree_item_activated() {
Dictionary d = ti->get_metadata(0);
if (d["dir"]) {
- dir_access->change_dir(d["name"]);
+ _change_dir(d["name"]);
if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY) {
file->set_text("");
}
- call_deferred(SNAME("_update_file_list"));
- call_deferred(SNAME("_update_dir"));
_push_history();
} else {
_action_pressed();
@@ -486,7 +480,12 @@ void FileDialog::update_file_name() {
String filter_str = filters[idx];
String file_str = file->get_text();
String base_name = file_str.get_basename();
- file_str = base_name + "." + filter_str.strip_edges().to_lower();
+ Vector<String> filter_substr = filter_str.split(";");
+ if (filter_substr.size() >= 2) {
+ file_str = base_name + "." + filter_substr[0].strip_edges().get_extension().to_lower();
+ } else {
+ file_str = base_name + "." + filter_str.strip_edges().get_extension().to_lower();
+ }
file->set_text(file_str);
}
}
@@ -704,9 +703,7 @@ String FileDialog::get_current_path() const {
}
void FileDialog::set_current_dir(const String &p_dir) {
- dir_access->change_dir(p_dir);
- update_dir();
- invalidate();
+ _change_dir(p_dir);
_push_history();
}
@@ -732,6 +729,27 @@ void FileDialog::set_current_path(const String &p_path) {
}
}
+void FileDialog::set_root_subfolder(const String &p_root) {
+ root_subfolder = p_root;
+ ERR_FAIL_COND_MSG(!dir_access->dir_exists(p_root), "root_subfolder must be an existing sub-directory.");
+
+ local_history.clear();
+ local_history_pos = -1;
+
+ dir_access->change_dir(root_subfolder);
+ if (root_subfolder.is_empty()) {
+ root_prefix = "";
+ } else {
+ root_prefix = dir_access->get_current_dir();
+ }
+ invalidate();
+ update_dir();
+}
+
+String FileDialog::get_root_subfolder() const {
+ return root_subfolder;
+}
+
void FileDialog::set_mode_overrides_title(bool p_override) {
mode_overrides_title = p_override;
}
@@ -810,6 +828,8 @@ void FileDialog::set_access(Access p_access) {
} break;
}
access = p_access;
+ root_prefix = "";
+ root_subfolder = "";
_update_drives();
invalidate();
update_filters();
@@ -832,10 +852,8 @@ FileDialog::Access FileDialog::get_access() const {
void FileDialog::_make_dir_confirm() {
Error err = dir_access->make_dir(makedirname->get_text().strip_edges());
if (err == OK) {
- dir_access->change_dir(makedirname->get_text().strip_edges());
- invalidate();
+ _change_dir(makedirname->get_text().strip_edges());
update_filters();
- update_dir();
_push_history();
} else {
mkdirerr->popup_centered(Size2(250, 50));
@@ -850,11 +868,25 @@ void FileDialog::_make_dir() {
void FileDialog::_select_drive(int p_idx) {
String d = drives->get_item_text(p_idx);
- dir_access->change_dir(d);
+ _change_dir(d);
file->set_text("");
+ _push_history();
+}
+
+void FileDialog::_change_dir(const String &p_new_dir) {
+ if (root_prefix.is_empty()) {
+ dir_access->change_dir(p_new_dir);
+ } else {
+ String old_dir = dir_access->get_current_dir();
+ dir_access->change_dir(p_new_dir);
+ if (!dir_access->get_current_dir(false).begins_with(root_prefix)) {
+ dir_access->change_dir(old_dir);
+ return;
+ }
+ }
+
invalidate();
update_dir();
- _push_history();
}
void FileDialog::_update_drives(bool p_select) {
@@ -904,6 +936,8 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit);
ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access);
ClassDB::bind_method(D_METHOD("get_access"), &FileDialog::get_access);
+ ClassDB::bind_method(D_METHOD("set_root_subfolder", "dir"), &FileDialog::set_root_subfolder);
+ ClassDB::bind_method(D_METHOD("get_root_subfolder"), &FileDialog::get_root_subfolder);
ClassDB::bind_method(D_METHOD("set_show_hidden_files", "show"), &FileDialog::set_show_hidden_files);
ClassDB::bind_method(D_METHOD("is_showing_hidden_files"), &FileDialog::is_showing_hidden_files);
ClassDB::bind_method(D_METHOD("_update_file_name"), &FileDialog::update_file_name);
@@ -916,6 +950,7 @@ void FileDialog::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User Data,File System"), "set_access", "get_access");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "root_subfolder"), "set_root_subfolder", "get_root_subfolder");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 2e326d2949..8b8d93920c 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -101,6 +101,8 @@ private:
void _push_history();
bool mode_overrides_title = true;
+ String root_subfolder;
+ String root_prefix;
static bool default_show_hidden_files;
bool show_hidden_files = false;
@@ -131,6 +133,7 @@ private:
void _go_back();
void _go_forward();
+ void _change_dir(const String &p_new_dir);
void _update_drives(bool p_select = true);
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
@@ -162,6 +165,9 @@ public:
void set_current_file(const String &p_file);
void set_current_path(const String &p_path);
+ void set_root_subfolder(const String &p_root);
+ String get_root_subfolder() const;
+
void set_mode_overrides_title(bool p_override);
bool is_mode_overriding_title() const;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 87706cd0d7..92016ca42e 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -44,26 +44,6 @@ struct _MinSizeCache {
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- _shape();
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- _shape();
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
if (!str.begins_with("slot/")) {
return false;
@@ -106,18 +86,6 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
-
if (!str.begins_with("slot/")) {
return false;
}
@@ -156,12 +124,6 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
}
void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-
int idx = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -471,7 +433,7 @@ void GraphNode::_shape() {
} else {
title_buf->set_direction((TextServer::Direction)text_direction);
}
- title_buf->add_string(title, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ title_buf->add_string(title, font, font_size, language);
}
#ifdef TOOLS_ENABLED
@@ -726,29 +688,6 @@ Control::TextDirection GraphNode::get_text_direction() const {
return text_direction;
}
-void GraphNode::clear_opentype_features() {
- opentype_features.clear();
- _shape();
- update();
-}
-
-void GraphNode::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- _shape();
- update();
- }
-}
-
-int GraphNode::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void GraphNode::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -1043,9 +982,6 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_title"), &GraphNode::get_title);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &GraphNode::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &GraphNode::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &GraphNode::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &GraphNode::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &GraphNode::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &GraphNode::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &GraphNode::get_language);
@@ -1105,8 +1041,6 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_overlay"), &GraphNode::get_overlay);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
@@ -1114,6 +1048,10 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "comment"), "set_comment", "is_comment");
ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay");
+ ADD_GROUP("BiDi", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+
ADD_SIGNAL(MethodInfo("position_offset_changed"));
ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "idx")));
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "from"), PropertyInfo(Variant::VECTOR2, "to")));
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index f6c943dc89..0651eb5cc9 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -60,7 +60,6 @@ private:
String title;
Ref<TextLine> title_buf;
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@@ -148,10 +147,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index aeb5338022..1d4ca4d196 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -43,7 +43,7 @@ void ItemList::_shape(int p_idx) {
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
- item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.opentype_features, (!item.language.is_empty()) ? item.language : TranslationServer::get_singleton()->get_tool_locale());
+ item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
item.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
@@ -117,35 +117,6 @@ Control::TextDirection ItemList::get_item_text_direction(int p_idx) const {
return items[p_idx].text_direction;
}
-void ItemList::clear_item_opentype_features(int p_idx) {
- ERR_FAIL_INDEX(p_idx, items.size());
- items.write[p_idx].opentype_features.clear();
- _shape(p_idx);
- update();
-}
-
-void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) {
- if (p_idx < 0) {
- p_idx += get_item_count();
- }
- ERR_FAIL_INDEX(p_idx, items.size());
- int32_t tag = TS->name_to_tag(p_name);
- if (!items[p_idx].opentype_features.has(tag) || (int)items[p_idx].opentype_features[tag] != p_value) {
- items.write[p_idx].opentype_features[tag] = p_value;
- _shape(p_idx);
- update();
- }
-}
-
-int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const {
- ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
- int32_t tag = TS->name_to_tag(p_name);
- if (!items[p_idx].opentype_features.has(tag)) {
- return -1;
- }
- return items[p_idx].opentype_features[tag];
-}
-
void ItemList::set_item_language(int p_idx, const String &p_language) {
if (p_idx < 0) {
p_idx += get_item_count();
@@ -1656,10 +1627,6 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_text_direction", "idx", "direction"), &ItemList::set_item_text_direction);
ClassDB::bind_method(D_METHOD("get_item_text_direction", "idx"), &ItemList::get_item_text_direction);
- ClassDB::bind_method(D_METHOD("set_item_opentype_feature", "idx", "tag", "value"), &ItemList::set_item_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_item_opentype_feature", "idx", "tag"), &ItemList::get_item_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_item_opentype_features", "idx"), &ItemList::clear_item_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_item_language", "idx", "language"), &ItemList::set_item_language);
ClassDB::bind_method(D_METHOD("get_item_language", "idx"), &ItemList::get_item_language);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index a15b090149..c7d87da0b5 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -58,7 +58,6 @@ private:
Ref<Texture2D> tag_icon;
String text;
Ref<TextParagraph> text_buf;
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
@@ -145,10 +144,6 @@ public:
void set_item_text_direction(int p_idx, TextDirection p_text_direction);
TextDirection get_item_text_direction(int p_idx) const;
- void set_item_opentype_feature(int p_idx, const String &p_name, int p_value);
- int get_item_opentype_feature(int p_idx, const String &p_name) const;
- void clear_item_opentype_features(int p_idx);
-
void set_item_language(int p_idx, const String &p_language);
String get_item_language(int p_idx) const;
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 82ab7c2e18..5dec1df4a5 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -66,11 +66,11 @@ bool Label::is_uppercase() const {
int Label::get_line_height(int p_line) const {
Ref<Font> font = get_theme_font(SNAME("font"));
if (p_line >= 0 && p_line < lines_rid.size()) {
- return TS->shaped_text_get_size(lines_rid[p_line]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
+ return TS->shaped_text_get_size(lines_rid[p_line]).y;
} else if (lines_rid.size() > 0) {
int h = 0;
for (int i = 0; i < lines_rid.size(); i++) {
- h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
+ h = MAX(h, TS->shaped_text_get_size(lines_rid[i]).y);
}
return h;
} else {
@@ -83,7 +83,6 @@ void Label::_shape() {
int width = (get_size().width - style->get_minimum_size().width);
if (dirty || font_dirty) {
- String lang = (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale();
if (dirty) {
TS->shaped_text_clear(text_rid);
}
@@ -95,18 +94,21 @@ void Label::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null());
- String text = (uppercase) ? TS->string_to_upper(xl_text, lang) : xl_text;
+ String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
text = text.substr(0, visible_chars);
}
if (dirty) {
- TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, lang);
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
} else {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
- TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
}
}
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text));
dirty = false;
font_dirty = false;
@@ -233,7 +235,7 @@ void Label::_update_visible() {
minsize.height = 0;
int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped);
for (int64_t i = lines_skipped; i < last_line; i++) {
- minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (minsize.height > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@@ -314,7 +316,7 @@ void Label::_notification(int p_what) {
// Get number of lines to fit to the height.
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@@ -334,7 +336,7 @@ void Label::_notification(int p_what) {
int total_glyphs = 0;
total_h = 0;
for (int64_t i = lines_skipped; i < last_line; i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]);
}
int visible_glyphs = total_glyphs * percent_visible;
@@ -374,7 +376,7 @@ void Label::_notification(int p_what) {
for (int i = lines_skipped; i < last_line; i++) {
Size2 line_size = TS->shaped_text_get_size(lines_rid[i]);
ofs.x = 0;
- ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP);
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[i]);
switch (horizontal_alignment) {
case HORIZONTAL_ALIGNMENT_FILL:
if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) {
@@ -527,7 +529,7 @@ void Label::_notification(int p_what) {
}
}
}
- ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM);
+ ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing;
}
} break;
@@ -551,7 +553,7 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
Ref<Font> font = get_theme_font(SNAME("font"));
- min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
+ min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size(SNAME("font_size"))));
Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
@@ -582,7 +584,7 @@ int Label::get_visible_line_count() const {
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
- total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
@@ -674,29 +676,6 @@ Control::TextDirection Label::get_text_direction() const {
return text_direction;
}
-void Label::clear_opentype_features() {
- opentype_features.clear();
- font_dirty = true;
- update();
-}
-
-void Label::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- font_dirty = true;
- update();
- }
-}
-
-int Label::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void Label::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -818,56 +797,6 @@ int Label::get_total_character_count() const {
return xl_text.length();
}
-bool Label::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- font_dirty = true;
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- font_dirty = true;
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool Label::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void Label::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label::set_horizontal_alignment);
ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &Label::get_horizontal_alignment);
@@ -877,9 +806,6 @@ void Label::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &Label::get_text);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Label::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Label::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Label::get_language);
ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label::set_autowrap_mode);
@@ -924,11 +850,9 @@ void Label::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
- ADD_GROUP("Locale", "");
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
-
- ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
diff --git a/scene/gui/label.h b/scene/gui/label.h
index fac3d75a1b..a59d35950d 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -53,7 +53,6 @@ private:
RID text_rid;
Vector<RID> lines_rid;
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@@ -74,10 +73,6 @@ protected:
static void _bind_methods();
- 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;
-
public:
virtual Size2 get_minimum_size() const override;
@@ -93,10 +88,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 540250c8e9..39f8f23cd8 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -744,6 +744,17 @@ void LineEdit::_notification(int p_what) {
update();
} break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ if (caret_blinking) {
+ caret_blink_timer += get_process_delta_time();
+
+ if (caret_blink_timer >= caret_blink_speed) {
+ caret_blink_timer = 0.0;
+ _toggle_draw_caret();
+ }
+ }
+ } break;
+
case NOTIFICATION_DRAW: {
if ((!has_focus() && !(menu && menu->has_focus()) && !caret_force_displayed) || !window_has_focus) {
draw_caret = false;
@@ -776,7 +787,7 @@ void LineEdit::_notification(int p_what) {
int x_ofs = 0;
bool using_placeholder = text.is_empty() && ime_text.is_empty();
float text_width = TS->shaped_text_get_size(text_rid).x;
- float text_height = TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
+ float text_height = TS->shaped_text_get_size(text_rid).y;
switch (alignment) {
case HORIZONTAL_ALIGNMENT_FILL:
@@ -991,8 +1002,9 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_ENTER: {
if (!caret_force_displayed) {
if (caret_blink_enabled) {
- if (caret_blink_timer->is_stopped()) {
- caret_blink_timer->start();
+ if (!caret_blinking) {
+ caret_blinking = true;
+ caret_blink_timer = 0.0;
}
} else {
draw_caret = true;
@@ -1010,7 +1022,7 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
if (caret_blink_enabled && !caret_force_displayed) {
- caret_blink_timer->stop();
+ caret_blinking = false;
}
if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) {
@@ -1318,14 +1330,16 @@ bool LineEdit::is_caret_blink_enabled() const {
void LineEdit::set_caret_blink_enabled(const bool p_enabled) {
caret_blink_enabled = p_enabled;
+ set_process_internal(p_enabled);
if (has_focus() || caret_force_displayed) {
if (p_enabled) {
- if (caret_blink_timer->is_stopped()) {
- caret_blink_timer->start();
+ if (!caret_blinking) {
+ caret_blinking = true;
+ caret_blink_timer = 0.0;
}
} else {
- caret_blink_timer->stop();
+ caret_blinking = false;
}
}
@@ -1345,20 +1359,19 @@ void LineEdit::set_caret_force_displayed(const bool p_enabled) {
}
float LineEdit::get_caret_blink_speed() const {
- return caret_blink_timer->get_wait_time();
+ return caret_blink_speed;
}
void LineEdit::set_caret_blink_speed(const float p_speed) {
ERR_FAIL_COND(p_speed <= 0);
- caret_blink_timer->set_wait_time(p_speed);
+ caret_blink_speed = p_speed;
}
void LineEdit::_reset_caret_blink_timer() {
if (caret_blink_enabled) {
draw_caret = true;
if (has_focus()) {
- caret_blink_timer->stop();
- caret_blink_timer->start();
+ caret_blink_timer = 0.0;
update();
}
}
@@ -1438,29 +1451,6 @@ Control::TextDirection LineEdit::get_text_direction() const {
return text_direction;
}
-void LineEdit::clear_opentype_features() {
- opentype_features.clear();
- _shape();
- update();
-}
-
-void LineEdit::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- _shape();
- update();
- }
-}
-
-int LineEdit::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void LineEdit::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -1675,7 +1665,7 @@ Size2 LineEdit::get_minimum_size() const {
Size2 min_size;
// Minimum size of text.
- float em_space_size = font->get_char_size('M', 0, font_size).x;
+ float em_space_size = font->get_char_size('M', font_size).x;
min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
if (expand_to_text_length) {
@@ -1683,7 +1673,7 @@ Size2 LineEdit::get_minimum_size() const {
min_size.width = MAX(min_size.width, full_width + em_space_size);
}
- min_size.height = MAX(TS->shaped_text_get_size(text_rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM), font->get_height(font_size));
+ min_size.height = MAX(TS->shaped_text_get_size(text_rid).y, font->get_height(font_size));
// Take icons into account.
int icon_max_width = 0;
@@ -2142,7 +2132,10 @@ void LineEdit::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null());
- TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, t));
full_width = TS->shaped_text_get_size(text_rid).x;
@@ -2223,56 +2216,6 @@ Key LineEdit::_get_menu_action_accelerator(const String &p_action) {
}
}
-bool LineEdit::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- _shape();
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- _shape();
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool LineEdit::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void LineEdit::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
void LineEdit::_validate_property(PropertyInfo &property) const {
if (!caret_blink_enabled && property.name == "caret_blink_speed") {
property.usage = PROPERTY_USAGE_NO_EDITOR;
@@ -2298,9 +2241,6 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_control_chars", "enable"), &LineEdit::set_draw_control_chars);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LineEdit::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &LineEdit::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &LineEdit::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &LineEdit::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &LineEdit::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LineEdit::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &LineEdit::get_language);
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &LineEdit::set_structured_text_bidi_override);
@@ -2406,18 +2346,20 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
- ADD_GROUP("Structured Text", "structured_text_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
+
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_caret_column", "get_caret_column");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_force_displayed"), "set_caret_force_displayed", "is_caret_force_displayed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
+
+ ADD_GROUP("BiDi", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
void LineEdit::_ensure_menu() {
@@ -2508,10 +2450,6 @@ LineEdit::LineEdit(const String &p_placeholder) {
set_mouse_filter(MOUSE_FILTER_STOP);
set_process_unhandled_key_input(true);
- caret_blink_timer = memnew(Timer);
- add_child(caret_blink_timer, false, INTERNAL_MODE_FRONT);
- caret_blink_timer->set_wait_time(0.65);
- caret_blink_timer->connect("timeout", callable_mp(this, &LineEdit::_toggle_draw_caret));
set_caret_blink_enabled(false);
set_placeholder(p_placeholder);
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 0fb178fca4..557da35bfd 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -105,7 +105,6 @@ private:
int scroll_offset = 0;
int max_length = 0; // 0 for no maximum.
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextDirection input_direction = TEXT_DIRECTION_LTR;
@@ -160,7 +159,9 @@ private:
bool caret_blink_enabled = false;
bool caret_force_displayed = false;
bool draw_caret = true;
- Timer *caret_blink_timer = nullptr;
+ float caret_blink_speed = 0.65;
+ double caret_blink_timer = 0.0;
+ bool caret_blinking = false;
bool _is_over_clear_button(const Point2 &p_pos) const;
@@ -208,9 +209,6 @@ protected:
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
- 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;
void _validate_property(PropertyInfo &property) const override;
public:
@@ -246,10 +244,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index dca6437519..30c0bb3321 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -43,7 +43,7 @@ void LinkButton::_shape() {
text_buf->set_direction((TextServer::Direction)text_direction);
}
TS->shaped_text_set_bidi_override(text_buf->get_rid(), structured_text_parser(st_parser, st_args, xl_text));
- text_buf->add_string(xl_text, font, font_size, opentype_features, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
+ text_buf->add_string(xl_text, font, font_size, language);
}
void LinkButton::set_text(const String &p_text) {
@@ -96,29 +96,6 @@ Control::TextDirection LinkButton::get_text_direction() const {
return text_direction;
}
-void LinkButton::clear_opentype_features() {
- opentype_features.clear();
- _shape();
- update();
-}
-
-void LinkButton::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- _shape();
- update();
- }
-}
-
-int LinkButton::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void LinkButton::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -237,64 +214,11 @@ void LinkButton::_notification(int p_what) {
}
}
-bool LinkButton::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- _shape();
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- _shape();
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool LinkButton::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void LinkButton::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
void LinkButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &LinkButton::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &LinkButton::get_text);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &LinkButton::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &LinkButton::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &LinkButton::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &LinkButton::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &LinkButton::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &LinkButton::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &LinkButton::get_language);
ClassDB::bind_method(D_METHOD("set_underline_mode", "underline_mode"), &LinkButton::set_underline_mode);
@@ -309,10 +233,11 @@ void LinkButton::_bind_methods() {
BIND_ENUM_CONSTANT(UNDERLINE_MODE_NEVER);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
+
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
- ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index 6d2dcbde84..54a31f06ce 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -50,7 +50,6 @@ private:
Ref<TextLine> text_buf;
UnderlineMode underline_mode = UNDERLINE_MODE_ALWAYS;
- Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@@ -63,10 +62,6 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- 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;
-
public:
void set_text(const String &p_text);
String get_text() const;
@@ -80,10 +75,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 5931c112eb..3a31246b17 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -760,11 +760,11 @@ void PopupMenu::_shape_item(int p_item) {
} else {
items.write[p_item].text_buf->set_direction((TextServer::Direction)items[p_item].text_direction);
}
- items.write[p_item].text_buf->add_string(items.write[p_item].xl_text, font, font_size, items[p_item].opentype_features, !items[p_item].language.is_empty() ? items[p_item].language : TranslationServer::get_singleton()->get_tool_locale());
+ items.write[p_item].text_buf->add_string(items.write[p_item].xl_text, font, font_size, items[p_item].language);
items.write[p_item].accel_text_buf->clear();
items.write[p_item].accel_text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
- items.write[p_item].accel_text_buf->add_string(_get_accel_text(items.write[p_item]), font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ items.write[p_item].accel_text_buf->add_string(_get_accel_text(items.write[p_item]), font, font_size);
items.write[p_item].dirty = false;
}
}
@@ -1067,29 +1067,6 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex
}
}
-void PopupMenu::clear_item_opentype_features(int p_item) {
- if (p_item < 0) {
- p_item += get_item_count();
- }
- ERR_FAIL_INDEX(p_item, items.size());
- items.write[p_item].opentype_features.clear();
- items.write[p_item].dirty = true;
- control->update();
-}
-
-void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int p_value) {
- if (p_item < 0) {
- p_item += get_item_count();
- }
- ERR_FAIL_INDEX(p_item, items.size());
- int32_t tag = TS->name_to_tag(p_name);
- if (!items[p_item].opentype_features.has(tag) || (int)items[p_item].opentype_features[tag] != p_value) {
- items.write[p_item].opentype_features[tag] = p_value;
- items.write[p_item].dirty = true;
- control->update();
- }
-}
-
void PopupMenu::set_item_language(int p_item, const String &p_language) {
if (p_item < 0) {
p_item += get_item_count();
@@ -1195,15 +1172,6 @@ Control::TextDirection PopupMenu::get_item_text_direction(int p_item) const {
return items[p_item].text_direction;
}
-int PopupMenu::get_item_opentype_feature(int p_item, const String &p_name) const {
- ERR_FAIL_INDEX_V(p_item, items.size(), -1);
- int32_t tag = TS->name_to_tag(p_name);
- if (!items[p_item].opentype_features.has(tag)) {
- return -1;
- }
- return items[p_item].opentype_features[tag];
-}
-
String PopupMenu::get_item_language(int p_item) const {
ERR_FAIL_INDEX_V(p_item, items.size(), "");
return items[p_item].language;
@@ -1853,7 +1821,6 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_text", "index", "text"), &PopupMenu::set_item_text);
ClassDB::bind_method(D_METHOD("set_item_text_direction", "index", "direction"), &PopupMenu::set_item_text_direction);
- ClassDB::bind_method(D_METHOD("set_item_opentype_feature", "index", "tag", "value"), &PopupMenu::set_item_opentype_feature);
ClassDB::bind_method(D_METHOD("set_item_language", "index", "language"), &PopupMenu::set_item_language);
ClassDB::bind_method(D_METHOD("set_item_icon", "index", "icon"), &PopupMenu::set_item_icon);
ClassDB::bind_method(D_METHOD("set_item_checked", "index", "checked"), &PopupMenu::set_item_checked);
@@ -1876,8 +1843,6 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_text", "index"), &PopupMenu::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_text_direction", "index"), &PopupMenu::get_item_text_direction);
- ClassDB::bind_method(D_METHOD("get_item_opentype_feature", "index", "tag"), &PopupMenu::get_item_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_item_opentype_features", "index"), &PopupMenu::clear_item_opentype_features);
ClassDB::bind_method(D_METHOD("get_item_language", "index"), &PopupMenu::get_item_language);
ClassDB::bind_method(D_METHOD("get_item_icon", "index"), &PopupMenu::get_item_icon);
ClassDB::bind_method(D_METHOD("is_item_checked", "index"), &PopupMenu::is_item_checked);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 8218c6122e..daa38b0e6d 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -47,7 +47,6 @@ class PopupMenu : public Popup {
Ref<TextLine> text_buf;
Ref<TextLine> accel_text_buf;
- Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_AUTO;
@@ -171,8 +170,6 @@ public:
void set_item_text(int p_idx, const String &p_text);
void set_item_text_direction(int p_idx, Control::TextDirection p_text_direction);
- void set_item_opentype_feature(int p_idx, const String &p_name, int p_value);
- void clear_item_opentype_features(int p_idx);
void set_item_language(int p_idx, const String &p_language);
void set_item_icon(int p_idx, const Ref<Texture2D> &p_icon);
void set_item_checked(int p_idx, bool p_checked);
@@ -195,7 +192,6 @@ public:
String get_item_text(int p_idx) const;
Control::TextDirection get_item_text_direction(int p_idx) const;
- int get_item_opentype_feature(int p_idx, const String &p_name) const;
String get_item_language(int p_idx) const;
int get_item_idx_from_text(const String &text) const;
Ref<Texture2D> get_item_icon(int p_idx) const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 0516c8e722..05824d54f1 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -227,8 +227,10 @@ void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref<
if (font_size == -1) {
font_size = p_base_font_size;
}
- Dictionary font_ftr = _find_font_features(it);
- TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font_ftr);
+ TS->shaped_set_span_update_font(t, i, font->get_rids(), font_size, font->get_opentype_features());
+ for (int j = 0; j < TextServer::SPACING_MAX; j++) {
+ TS->shaped_text_set_spacing(t, TextServer::SpacingType(j), font->get_spacing(TextServer::SpacingType(j)));
+ }
}
}
@@ -263,7 +265,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
- tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
+ tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@@ -453,7 +455,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (tab_size > 0) { // Align inline tabs.
Vector<float> tabs;
- tabs.push_back(tab_size * p_base_font->get_char_size(' ', 0, p_base_font_size).width);
+ tabs.push_back(tab_size * p_base_font->get_char_size(' ', p_base_font_size).width);
l.text_buf->tab_align(tabs);
}
@@ -483,7 +485,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (font_size == -1) {
font_size = p_base_font_size;
}
- l.text_buf->add_string("\n", font, font_size, Dictionary(), "");
+ l.text_buf->add_string("\n", font, font_size);
text += "\n";
l.char_count++;
remaining_characters--;
@@ -498,7 +500,6 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (font_size == -1) {
font_size = p_base_font_size;
}
- Dictionary font_ftr = _find_font_features(it);
String lang = _find_language(it);
String tx = t->text;
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters >= 0 && remaining_characters >= 0) {
@@ -506,7 +507,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
remaining_characters -= tx.length();
- l.text_buf->add_string(tx, font, font_size, font_ftr, lang, (uint64_t)it);
+ l.text_buf->add_string(tx, font, font_size, lang, (uint64_t)it);
text += tx;
l.char_count += tx.length();
} break;
@@ -837,7 +838,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
//draw_rect(Rect2(p_ofs + off, TS->shaped_text_get_size(rid)), Color(1,0,0), false, 2); //DEBUG_RECTS
- off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top();
+ off.y += TS->shaped_text_get_ascent(rid);
// Draw inlined objects.
Array objects = TS->shaped_text_get_objects(rid);
for (int i = 0; i < objects.size(); i++) {
@@ -1299,7 +1300,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw foreground color box
_draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 1);
- off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom();
+ off.y += TS->shaped_text_get_descent(rid);
}
return line_count;
@@ -1394,7 +1395,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
} break;
}
- off.y += TS->shaped_text_get_ascent(rid) + l.text_buf->get_spacing_top();
+ off.y += TS->shaped_text_get_ascent(rid);
Array objects = TS->shaped_text_get_objects(rid);
for (int i = 0; i < objects.size(); i++) {
@@ -1491,7 +1492,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
return table_offy;
}
- off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom() + get_theme_constant(SNAME("line_separation"));
+ off.y += TS->shaped_text_get_descent(rid) + get_theme_constant(SNAME("line_separation"));
}
// Text line hit.
@@ -2113,21 +2114,6 @@ int RichTextLabel::_find_outline_size(Item *p_item, int p_default) {
return p_default;
}
-Dictionary RichTextLabel::_find_font_features(Item *p_item) {
- Item *ffitem = p_item;
-
- while (ffitem) {
- if (ffitem->type == ITEM_FONT_FEATURES) {
- ItemFontFeatures *fi = static_cast<ItemFontFeatures *>(ffitem);
- return fi->opentype_features;
- }
-
- ffitem = ffitem->parent;
- }
-
- return Dictionary();
-}
-
RichTextLabel::ItemDropcap *RichTextLabel::_find_dc_item(Item *p_item) {
Item *item = p_item;
@@ -2204,7 +2190,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
- margin += tab_size * font->get_char_size(' ', 0, font_size).width;
+ margin += tab_size * font->get_char_size(' ', font_size).width;
} else if (item->type == ITEM_LIST) {
Ref<Font> font = _find_font(item);
@@ -2215,7 +2201,7 @@ int RichTextLabel::_find_margin(Item *p_item, const Ref<Font> &p_base_font, int
if (font_size == -1) {
font_size = p_base_font_size;
}
- margin += tab_size * font->get_char_size(' ', 0, font_size).width;
+ margin += tab_size * font->get_char_size(' ', font_size).width;
}
item = item->parent;
@@ -2584,8 +2570,8 @@ void RichTextLabel::_process_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
- Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
+ Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int ctrl_height = get_size().height;
int fi = main->first_invalid_line.load();
int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
@@ -2950,25 +2936,14 @@ void RichTextLabel::push_font_size(int p_font_size) {
_add_item(item, true);
}
-void RichTextLabel::push_font_features(const Dictionary &p_features) {
- _stop_thread();
- MutexLock data_lock(data_mutex);
-
- ERR_FAIL_COND(current->type == ITEM_TABLE);
- ItemFontFeatures *item = memnew(ItemFontFeatures);
-
- item->opentype_features = p_features;
- _add_item(item, true);
-}
-
-void RichTextLabel::push_outline_size(int p_font_size) {
+void RichTextLabel::push_outline_size(int p_ol_size) {
_stop_thread();
MutexLock data_lock(data_mutex);
ERR_FAIL_COND(current->type == ITEM_TABLE);
ItemOutlineSize *item = memnew(ItemOutlineSize);
- item->outline_size = p_font_size;
+ item->outline_size = p_ol_size;
_add_item(item, true);
}
@@ -3840,8 +3815,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front("hint");
} else if (tag.begins_with("dropcap")) {
Vector<String> subtag = tag.substr(5, tag.length()).split(" ");
- Ref<Font> f = get_theme_font(SNAME("normal_font"));
int fs = get_theme_font_size(SNAME("normal_font_size")) * 3;
+ Ref<Font> f = get_theme_font(SNAME("normal_font"));
Color color = get_theme_color(SNAME("default_color"));
Color outline_color = get_theme_color(SNAME("outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
@@ -3974,64 +3949,127 @@ void RichTextLabel::append_text(const String &p_bbcode) {
pos = brk_end + 1;
tag_stack.push_front("outline_color");
- } else if (tag.begins_with("font=")) {
- String fnt = tag.substr(5, tag.length());
-
- Ref<Font> font = ResourceLoader::load(fnt, "Font");
- if (font.is_valid()) {
- push_font(font);
- } else {
- push_font(normal_font);
- }
-
- pos = brk_end + 1;
- tag_stack.push_front("font");
} else if (tag.begins_with("font_size=")) {
int fnt_size = tag.substr(10, tag.length()).to_int();
push_font_size(fnt_size);
pos = brk_end + 1;
tag_stack.push_front("font_size");
+
} else if (tag.begins_with("opentype_features=")) {
String fnt_ftr = tag.substr(18, tag.length());
Vector<String> subtag = fnt_ftr.split(",");
- Dictionary ftrs;
- for (int i = 0; i < subtag.size(); i++) {
- Vector<String> subtag_a = subtag[i].split("=");
- if (subtag_a.size() == 2) {
- ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
- } else if (subtag_a.size() == 1) {
- ftrs[TS->name_to_tag(subtag_a[0])] = 1;
+ if (subtag.size() > 0) {
+ Ref<Font> font = _find_font(current);
+ if (font.is_null()) {
+ font = normal_font;
}
+ Ref<FontVariation> fc;
+ fc.instantiate();
+ fc->set_base_font(font);
+ Dictionary features;
+ for (int i = 0; i < subtag.size(); i++) {
+ Vector<String> subtag_a = subtag[i].split("=");
+ if (subtag_a.size() == 2) {
+ features[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
+ } else if (subtag_a.size() == 1) {
+ features[TS->name_to_tag(subtag_a[0])] = 1;
+ }
+ }
+ fc->set_opentype_features(features);
+ push_font(fc);
}
- push_font_features(ftrs);
pos = brk_end + 1;
tag_stack.push_front("opentype_features");
+
+ } else if (tag.begins_with("font=")) {
+ String fnt = tag.substr(5, tag.length());
+
+ Ref<Font> fc = ResourceLoader::load(fnt, "Font");
+ if (fc.is_valid()) {
+ push_font(fc);
+ }
+
+ pos = brk_end + 1;
+ tag_stack.push_front("font");
+
} else if (tag.begins_with("font ")) {
Vector<String> subtag = tag.substr(2, tag.length()).split(" ");
+ Ref<FontVariation> fc;
+ fc.instantiate();
for (int i = 1; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=", true, 2);
if (subtag_a.size() == 2) {
if (subtag_a[0] == "name" || subtag_a[0] == "n") {
String fnt = subtag_a[1];
- Ref<Font> font = ResourceLoader::load(fnt, "Font");
- if (font.is_valid()) {
- push_font(font);
- } else {
- push_font(normal_font);
+ Ref<Font> font_data = ResourceLoader::load(fnt, "Font");
+ if (font_data.is_valid()) {
+ fc->set_base_font(font_data);
}
} else if (subtag_a[0] == "size" || subtag_a[0] == "s") {
int fnt_size = subtag_a[1].to_int();
- push_font_size(fnt_size);
+ if (fnt_size > 0) {
+ push_font_size(fnt_size);
+ }
+ } else if (subtag_a[0] == "glyph_spacing" || subtag_a[0] == "gl") {
+ int spacing = subtag_a[1].to_int();
+ fc->set_spacing(TextServer::SPACING_GLYPH, spacing);
+ } else if (subtag_a[0] == "space_spacing" || subtag_a[0] == "sp") {
+ int spacing = subtag_a[1].to_int();
+ fc->set_spacing(TextServer::SPACING_SPACE, spacing);
+ } else if (subtag_a[0] == "top_spacing" || subtag_a[0] == "top") {
+ int spacing = subtag_a[1].to_int();
+ fc->set_spacing(TextServer::SPACING_TOP, spacing);
+ } else if (subtag_a[0] == "bottom_spacing" || subtag_a[0] == "bt") {
+ int spacing = subtag_a[1].to_int();
+ fc->set_spacing(TextServer::SPACING_BOTTOM, spacing);
+ } else if (subtag_a[0] == "embolden" || subtag_a[0] == "emb") {
+ float emb = subtag_a[1].to_float();
+ fc->set_variation_embolden(emb);
+ } else if (subtag_a[0] == "face_index" || subtag_a[0] == "fi") {
+ int fi = subtag_a[1].to_int();
+ fc->set_variation_face_index(fi);
+ } else if (subtag_a[0] == "slant" || subtag_a[0] == "sln") {
+ float slant = subtag_a[1].to_float();
+ fc->set_variation_transform(Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0));
+ } else if (subtag_a[0] == "opentype_variation" || subtag_a[0] == "otv") {
+ Dictionary variations;
+ if (!subtag_a[1].is_empty()) {
+ Vector<String> variation_tags = subtag_a[1].split(",");
+ for (int j = 0; j < variation_tags.size(); j++) {
+ Vector<String> subtag_b = variation_tags[j].split("=");
+ if (subtag_b.size() == 2) {
+ variations[TS->name_to_tag(subtag_b[0])] = subtag_b[1].to_float();
+ }
+ }
+ fc->set_variation_opentype(variations);
+ }
+ } else if (subtag_a[0] == "opentype_features" || subtag_a[0] == "otf") {
+ Dictionary features;
+ if (!subtag_a[1].is_empty()) {
+ Vector<String> feature_tags = subtag_a[1].split(",");
+ for (int j = 0; j < feature_tags.size(); j++) {
+ Vector<String> subtag_b = feature_tags[j].split("=");
+ if (subtag_b.size() == 2) {
+ features[TS->name_to_tag(subtag_b[0])] = subtag_b[1].to_float();
+ } else if (subtag_b.size() == 1) {
+ features[TS->name_to_tag(subtag_b[0])] = 1;
+ }
+ }
+ fc->set_opentype_features(features);
+ }
}
}
}
-
+ push_font(fc);
pos = brk_end + 1;
tag_stack.push_front("font");
+
} else if (tag.begins_with("outline_size=")) {
int fnt_size = tag.substr(13, tag.length()).to_int();
- push_outline_size(fnt_size);
+ if (fnt_size > 0) {
+ push_outline_size(fnt_size);
+ }
pos = brk_end + 1;
tag_stack.push_front("outline_size");
@@ -4854,7 +4892,6 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);
ClassDB::bind_method(D_METHOD("push_font_size", "font_size"), &RichTextLabel::push_font_size);
- ClassDB::bind_method(D_METHOD("push_font_features", "opentype_features"), &RichTextLabel::push_font_features);
ClassDB::bind_method(D_METHOD("push_normal"), &RichTextLabel::push_normal);
ClassDB::bind_method(D_METHOD("push_bold"), &RichTextLabel::push_bold);
ClassDB::bind_method(D_METHOD("push_bold_italics"), &RichTextLabel::push_bold_italics);
@@ -5018,11 +5055,9 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
- ADD_GROUP("Locale", "");
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
-
- ADD_GROUP("Structured Text", "structured_text_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index c697320976..3b6175e9cf 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -186,11 +186,6 @@ private:
ItemFontSize() { type = ITEM_FONT_SIZE; }
};
- struct ItemFontFeatures : public Item {
- Dictionary opentype_features;
- ItemFontFeatures() { type = ITEM_FONT_FEATURES; }
- };
-
struct ItemColor : public Item {
Color color;
ItemColor() { type = ITEM_COLOR; }
@@ -466,9 +461,8 @@ private:
Item *_get_item_at_pos(Item *p_item_from, Item *p_item_to, int p_position);
void _find_frame(Item *p_item, ItemFrame **r_frame, int *r_line);
- Ref<Font> _find_font(Item *p_item);
int _find_font_size(Item *p_item);
- Dictionary _find_font_features(Item *p_item);
+ Ref<Font> _find_font(Item *p_item);
int _find_outline_size(Item *p_item, int p_default);
ItemList *_find_list_item(Item *p_item);
ItemDropcap *_find_dc_item(Item *p_item);
@@ -525,7 +519,6 @@ public:
void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0));
void push_font(const Ref<Font> &p_font);
void push_font_size(int p_font_size);
- void push_font_features(const Dictionary &p_features);
void push_outline_size(int p_font_size);
void push_normal();
void push_bold();
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index b4c90596f9..d36a364677 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -311,7 +311,7 @@ void TabBar::_shape(int p_tab) {
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
}
- tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, !tabs[p_tab].language.is_empty() ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale());
+ tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].language);
}
void TabBar::_notification(int p_what) {
@@ -667,48 +667,6 @@ Control::TextDirection TabBar::get_tab_text_direction(int p_tab) const {
return tabs[p_tab].text_direction;
}
-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_cache();
- _ensure_no_over_offset();
- if (scroll_to_selected) {
- ensure_tab_visible(current);
- }
- update();
- update_minimum_size();
-}
-
-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) {
- tabs.write[p_tab].opentype_features[tag] = p_value;
-
- _shape(p_tab);
- _update_cache();
- _ensure_no_over_offset();
- if (scroll_to_selected) {
- ensure_tab_visible(current);
- }
- update();
- update_minimum_size();
- }
-}
-
-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)) {
- return -1;
- }
- return tabs[p_tab].opentype_features[tag];
-}
-
void TabBar::set_tab_language(int p_tab, const String &p_language) {
ERR_FAIL_INDEX(p_tab, tabs.size());
@@ -1553,9 +1511,6 @@ void TabBar::_bind_methods() {
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);
diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h
index 548a2e62af..d123385e47 100644
--- a/scene/gui/tab_bar.h
+++ b/scene/gui/tab_bar.h
@@ -57,7 +57,6 @@ private:
String text;
String xl_text;
- Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
@@ -137,10 +136,6 @@ public:
void set_tab_text_direction(int p_tab, TextDirection p_text_direction);
TextDirection get_tab_text_direction(int p_tab) const;
- void set_tab_opentype_feature(int p_tab, const String &p_name, int p_value);
- int get_tab_opentype_feature(int p_tab, const String &p_name) const;
- void clear_tab_opentype_features(int p_tab);
-
void set_tab_language(int p_tab, const String &p_language);
String get_tab_language(int p_tab) const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 5506616b7a..9c6cd6bdb2 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -75,14 +75,6 @@ int TextEdit::Text::get_tab_size() const {
return tab_size;
}
-void TextEdit::Text::set_font_features(const Dictionary &p_features) {
- if (opentype_features.hash() == p_features.hash()) {
- return;
- }
- opentype_features = p_features;
- is_dirty = true;
-}
-
void TextEdit::Text::set_direction_and_language(TextServer::Direction p_direction, const String &p_language) {
if (direction == p_direction && language == p_language) {
return;
@@ -178,7 +170,7 @@ void TextEdit::Text::_calculate_max_line_width() {
void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_changed, const String &p_ime_text, const Array &p_bidi_override) {
ERR_FAIL_INDEX(p_line, text.size());
- if (font.is_null() || font_size <= 0) {
+ if (font.is_null()) {
return; // Not in tree?
}
@@ -191,14 +183,14 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
text.write[p_line].data_buf->set_preserve_control(draw_control_chars);
if (p_ime_text.length() > 0) {
if (p_text_changed) {
- text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, opentype_features, language);
+ text.write[p_line].data_buf->add_string(p_ime_text, font, font_size, language);
}
if (!p_bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), p_bidi_override);
}
} else {
if (p_text_changed) {
- text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, opentype_features, language);
+ text.write[p_line].data_buf->add_string(text[p_line].data, font, font_size, language);
}
if (!text[p_line].bidi_override.is_empty()) {
TS->shaped_text_set_bidi_override(text.write[p_line].data_buf->get_rid(), text[p_line].bidi_override);
@@ -209,14 +201,17 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan
RID r = text.write[p_line].data_buf->get_rid();
int spans = TS->shaped_get_span_count(r);
for (int i = 0; i < spans; i++) {
- TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, opentype_features);
+ TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, font->get_opentype_features());
+ }
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(r, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
}
// Apply tab align.
if (tab_size > 0) {
Vector<float> tabs;
- tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
+ tabs.push_back(font->get_char_size(' ', font_size).width * tab_size);
text.write[p_line].data_buf->tab_align(tabs);
}
@@ -255,7 +250,7 @@ void TextEdit::Text::invalidate_all_lines() {
if (tab_size_dirty) {
if (tab_size > 0) {
Vector<float> tabs;
- tabs.push_back(font->get_char_size(' ', 0, font_size).width * tab_size);
+ tabs.push_back(font->get_char_size(' ', font_size).width * tab_size);
text.write[i].data_buf->tab_align(tabs);
}
// Tabs have changes, force width update.
@@ -277,7 +272,7 @@ void TextEdit::Text::invalidate_font() {
max_width = -1;
line_height = -1;
- if (!font.is_null() && font_size > 0) {
+ if (font.is_valid() && font_size > 0) {
font_height = font->get_height(font_size);
}
@@ -295,7 +290,7 @@ void TextEdit::Text::invalidate_all() {
max_width = -1;
line_height = -1;
- if (!font.is_null() && font_size > 0) {
+ if (font.is_valid() && font_size > 0) {
font_height = font->get_height(font_size);
}
@@ -973,7 +968,7 @@ void TextEdit::_notification(int p_what) {
// Give visual indication of empty selected line.
if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) {
- float char_w = font->get_char_size(' ', 0, font_size).width;
+ float char_w = font->get_char_size(' ', font_size).width;
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), selection_color);
} else {
@@ -1071,7 +1066,7 @@ void TextEdit::_notification(int p_what) {
// Draw line.
RID rid = ldata->get_line_rid(line_wrap_index);
- float text_height = TS->shaped_text_get_size(rid).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM);
+ float text_height = TS->shaped_text_get_size(rid).y;
if (rtl) {
char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x;
@@ -1355,7 +1350,7 @@ void TextEdit::_notification(int p_what) {
ts_caret.l_caret.size.y = caret_width;
}
if (ts_caret.l_caret.position.x >= TS->shaped_text_get_size(rid).x) {
- ts_caret.l_caret.size.x = font->get_char_size('m', 0, font_size).x;
+ ts_caret.l_caret.size.x = font->get_char_size('m', font_size).x;
} else {
ts_caret.l_caret.size.x = 3 * caret_width;
}
@@ -2573,7 +2568,7 @@ void TextEdit::_update_placeholder() {
placeholder_data_buf->set_width(text.get_width());
placeholder_data_buf->set_direction((TextServer::Direction)text_direction);
placeholder_data_buf->set_preserve_control(draw_control_chars);
- placeholder_data_buf->add_string(placeholder_text, font, font_size, opentype_features, language);
+ placeholder_data_buf->add_string(placeholder_text, font, font_size, language);
placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text);
if (placeholder_bidi_override.is_empty()) {
@@ -2582,7 +2577,7 @@ void TextEdit::_update_placeholder() {
if (get_tab_size() > 0) {
Vector<float> tabs;
- tabs.push_back(font->get_char_size(' ', 0, font_size).width * get_tab_size());
+ tabs.push_back(font->get_char_size(' ', font_size).width * get_tab_size());
placeholder_data_buf->tab_align(tabs);
}
@@ -2653,7 +2648,6 @@ void TextEdit::_update_caches() {
dir = (TextServer::Direction)text_direction;
}
text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale());
- text.set_font_features(opentype_features);
text.set_draw_control_chars(draw_control_chars);
text.set_font(font);
text.set_font_size(font_size);
@@ -2668,7 +2662,11 @@ void TextEdit::_update_caches() {
/* General overrides. */
Size2 TextEdit::get_minimum_size() const {
- return style_normal->get_minimum_size();
+ Size2 size = style_normal->get_minimum_size();
+ if (fit_content_height) {
+ size.y += content_height_cache;
+ }
+ return size;
}
bool TextEdit::is_text_field() const {
@@ -2854,33 +2852,6 @@ Control::TextDirection TextEdit::get_text_direction() const {
return text_direction;
}
-void TextEdit::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- text.set_font_features(opentype_features);
- text.invalidate_font();
- _update_placeholder();
- update();
- }
-}
-
-int TextEdit::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
-void TextEdit::clear_opentype_features() {
- opentype_features.clear();
- text.set_font_features(opentype_features);
- text.invalidate_font();
- _update_placeholder();
- update();
-}
-
void TextEdit::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
@@ -4499,6 +4470,18 @@ float TextEdit::get_v_scroll_speed() const {
return v_scroll_speed;
}
+void TextEdit::set_fit_content_height_enabled(const bool p_enabled) {
+ if (fit_content_height == p_enabled) {
+ return;
+ }
+ fit_content_height = p_enabled;
+ update_minimum_size();
+}
+
+bool TextEdit::is_fit_content_height_enabled() const {
+ return fit_content_height;
+}
+
double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const {
ERR_FAIL_INDEX_V(p_line, text.size(), 0);
ERR_FAIL_COND_V(p_wrap_index < 0, 0);
@@ -5055,10 +5038,6 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextEdit::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &TextEdit::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &TextEdit::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &TextEdit::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &TextEdit::clear_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_language", "language"), &TextEdit::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &TextEdit::get_language);
@@ -5091,6 +5070,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &TextEdit::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text);
+
ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count);
ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &TextEdit::set_placeholder);
@@ -5297,7 +5277,7 @@ void TextEdit::_bind_methods() {
/* Viewport. */
// Scrolling.
- ClassDB::bind_method(D_METHOD("set_smooth_scroll_enable", "enable"), &TextEdit::set_smooth_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("set_smooth_scroll_enabled", "enable"), &TextEdit::set_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &TextEdit::set_v_scroll);
@@ -5312,6 +5292,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_scroll_speed", "speed"), &TextEdit::set_v_scroll_speed);
ClassDB::bind_method(D_METHOD("get_v_scroll_speed"), &TextEdit::get_v_scroll_speed);
+ ClassDB::bind_method(D_METHOD("set_fit_content_height_enabled"), &TextEdit::set_fit_content_height_enabled);
+ ClassDB::bind_method(D_METHOD("is_fit_content_height_enabled"), &TextEdit::is_fit_content_height_enabled);
+
ClassDB::bind_method(D_METHOD("get_scroll_pos_for_line", "line", "wrap_index"), &TextEdit::get_scroll_pos_for_line, DEFVAL(0));
// Visible lines.
@@ -5408,8 +5391,6 @@ void TextEdit::_bind_methods() {
/* Inspector */
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text", PROPERTY_HINT_MULTILINE_TEXT), "set_placeholder", "get_placeholder");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
@@ -5431,11 +5412,12 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "syntax_highlighter", PROPERTY_HINT_RESOURCE_TYPE, "SyntaxHighlighter", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_syntax_highlighter", "get_syntax_highlighter");
ADD_GROUP("Scroll", "scroll_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enabled", "is_smooth_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_past_end_of_file"), "set_scroll_past_end_of_file_enabled", "is_scroll_past_end_of_file_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_fit_content_height"), "set_fit_content_height_enabled", "is_fit_content_height_enabled");
ADD_GROUP("Minimap", "minimap_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "minimap_draw"), "set_draw_minimap", "is_drawing_minimap");
@@ -5448,7 +5430,9 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_move_on_right_click"), "set_move_caret_on_right_click_enabled", "is_move_caret_on_right_click_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
- ADD_GROUP("Structured Text", "structured_text_");
+ ADD_GROUP("BiDi", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
@@ -5473,60 +5457,6 @@ void TextEdit::_bind_methods() {
ProjectSettings::get_singleton()->set_custom_property_info("gui/common/text_edit_undo_stack_max_size", PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater")); // No negative numbers.
}
-bool TextEdit::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- text.set_font_features(opentype_features);
- text.invalidate_font();
- _update_placeholder();
- update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- text.set_font_features(opentype_features);
- text.invalidate_font();
- _update_placeholder();
- update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool TextEdit::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void TextEdit::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
/* Internal API for CodeEdit. */
// Line hiding.
void TextEdit::_set_hiding_enabled(bool p_enabled) {
@@ -6197,6 +6127,11 @@ void TextEdit::_update_scrollbars() {
total_width += minimap_width;
}
+ content_height_cache = MAX(total_rows, 1) * get_line_height();
+ if (fit_content_height) {
+ update_minimum_size();
+ }
+
updating_scrolls = true;
if (total_rows > visible_rows) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 9de2982d0a..6711cf8c7f 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -160,7 +160,6 @@ private:
int font_size = -1;
int font_height = 0;
- Dictionary opentype_features;
String language;
TextServer::Direction direction = TextServer::DIRECTION_AUTO;
bool draw_control_chars = false;
@@ -180,7 +179,6 @@ private:
int get_tab_size() const;
void set_font(const Ref<Font> &p_font);
void set_font_size(int p_font_size);
- void set_font_features(const Dictionary &p_features);
void set_direction_and_language(TextServer::Direction p_direction, const String &p_language);
void set_draw_control_chars(bool p_enabled);
@@ -271,7 +269,6 @@ private:
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextDirection input_direction = TEXT_DIRECTION_LTR;
- Dictionary opentype_features;
String language = "";
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@@ -456,6 +453,8 @@ private:
HScrollBar *h_scroll = nullptr;
VScrollBar *v_scroll = nullptr;
+ float content_height_cache = 0.0;
+ bool fit_content_height = false;
bool scroll_past_end_of_file_enabled = false;
// Smooth scrolling.
@@ -579,10 +578,6 @@ protected:
static void _bind_methods();
- 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;
-
/* Internal API for CodeEdit, pending public API. */
// brace matching
bool highlight_matching_braces_enabled = false;
@@ -648,10 +643,6 @@ public:
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
@@ -684,6 +675,7 @@ public:
void set_text(const String &p_text);
String get_text() const;
+
int get_line_count() const;
void set_placeholder(const String &p_text);
@@ -851,6 +843,9 @@ public:
void set_v_scroll_speed(float p_speed);
float get_v_scroll_speed() const;
+ void set_fit_content_height_enabled(const bool p_enabled);
+ bool is_fit_content_height_enabled() const;
+
double get_scroll_pos_for_line(int p_line, int p_wrap_index = 0) const;
// Visible lines.
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index d3e7540790..4bb8208679 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -303,37 +303,6 @@ Control::TextDirection TreeItem::get_text_direction(int p_column) const {
return cells[p_column].text_direction;
}
-void TreeItem::clear_opentype_features(int p_column) {
- ERR_FAIL_INDEX(p_column, cells.size());
-
- cells.write[p_column].opentype_features.clear();
- cells.write[p_column].dirty = true;
- cells.write[p_column].cached_minimum_size_dirty = true;
-
- _changed_notify(p_column);
-}
-
-void TreeItem::set_opentype_feature(int p_column, const String &p_name, int p_value) {
- ERR_FAIL_INDEX(p_column, cells.size());
- int32_t tag = TS->name_to_tag(p_name);
- if (!cells[p_column].opentype_features.has(tag) || (int)cells[p_column].opentype_features[tag] != p_value) {
- cells.write[p_column].opentype_features[tag] = p_value;
- cells.write[p_column].dirty = true;
- cells.write[p_column].cached_minimum_size_dirty = true;
-
- _changed_notify(p_column);
- }
-}
-
-int TreeItem::get_opentype_feature(int p_column, const String &p_name) const {
- ERR_FAIL_INDEX_V(p_column, cells.size(), -1);
- int32_t tag = TS->name_to_tag(p_name);
- if (!cells[p_column].opentype_features.has(tag)) {
- return -1;
- }
- return cells[p_column].opentype_features[tag];
-}
-
void TreeItem::set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser) {
ERR_FAIL_INDEX(p_column, cells.size());
@@ -1269,10 +1238,6 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "column", "direction"), &TreeItem::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction", "column"), &TreeItem::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "column", "tag", "value"), &TreeItem::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "column", "tag"), &TreeItem::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features", "column"), &TreeItem::clear_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "column", "parser"), &TreeItem::set_structured_text_bidi_override);
ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override", "column"), &TreeItem::get_structured_text_bidi_override);
@@ -1667,7 +1632,7 @@ void Tree::update_column(int p_col) {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
- columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].opentype_features, !columns[p_col].language.is_empty() ? columns[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+ columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].language);
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@@ -1725,7 +1690,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
} else {
font_size = cache.font_size;
}
- p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].opentype_features, !p_item->cells[p_col].language.is_empty() ? p_item->cells[p_col].language : TranslationServer::get_singleton()->get_tool_locale());
+ p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
p_item->cells.write[p_col].dirty = false;
}
@@ -3002,6 +2967,15 @@ void Tree::_go_down() {
accept_event();
}
+bool Tree::_scroll(bool p_horizontal, float p_pages) {
+ ScrollBar *scroll = p_horizontal ? (ScrollBar *)h_scroll : (ScrollBar *)v_scroll;
+
+ double prev_value = scroll->get_value();
+ scroll->set_value(scroll->get_value() + scroll->get_page() * p_pages);
+
+ return scroll->get_value() != prev_value;
+}
+
void Tree::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
@@ -3516,17 +3490,25 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
} break;
case MouseButton::WHEEL_UP: {
- double prev_value = v_scroll->get_value();
- v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * mb->get_factor() / 8);
- if (v_scroll->get_value() != prev_value) {
+ if (_scroll(false, -mb->get_factor() / 8)) {
accept_event();
}
} break;
case MouseButton::WHEEL_DOWN: {
- double prev_value = v_scroll->get_value();
- v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb->get_factor() / 8);
- if (v_scroll->get_value() != prev_value) {
+ if (_scroll(false, mb->get_factor() / 8)) {
+ accept_event();
+ }
+
+ } break;
+ case MouseButton::WHEEL_LEFT: {
+ if (_scroll(true, -mb->get_factor() / 8)) {
+ accept_event();
+ }
+
+ } break;
+ case MouseButton::WHEEL_RIGHT: {
+ if (_scroll(true, mb->get_factor() / 8)) {
accept_event();
}
@@ -4192,7 +4174,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, cache.font_size).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, HORIZONTAL_ALIGNMENT_LEFT, -1, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
}
if (!columns[p_column].clip_content) {
@@ -4471,32 +4453,6 @@ Control::TextDirection Tree::get_column_title_direction(int p_column) const {
return columns[p_column].text_direction;
}
-void Tree::clear_column_title_opentype_features(int p_column) {
- ERR_FAIL_INDEX(p_column, columns.size());
- columns.write[p_column].opentype_features.clear();
- update_column(p_column);
- update();
-}
-
-void Tree::set_column_title_opentype_feature(int p_column, const String &p_name, int p_value) {
- ERR_FAIL_INDEX(p_column, columns.size());
- int32_t tag = TS->name_to_tag(p_name);
- if (!columns[p_column].opentype_features.has(tag) || (int)columns[p_column].opentype_features[tag] != p_value) {
- columns.write[p_column].opentype_features[tag] = p_value;
- update_column(p_column);
- update();
- }
-}
-
-int Tree::get_column_title_opentype_feature(int p_column, const String &p_name) const {
- ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- int32_t tag = TS->name_to_tag(p_name);
- if (!columns[p_column].opentype_features.has(tag)) {
- return -1;
- }
- return columns[p_column].opentype_features[tag];
-}
-
void Tree::set_column_title_language(int p_column, const String &p_language) {
ERR_FAIL_INDEX(p_column, columns.size());
if (columns[p_column].language != p_language) {
@@ -4983,10 +4939,6 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_column_title_direction", "column", "direction"), &Tree::set_column_title_direction);
ClassDB::bind_method(D_METHOD("get_column_title_direction", "column"), &Tree::get_column_title_direction);
- ClassDB::bind_method(D_METHOD("set_column_title_opentype_feature", "column", "tag", "value"), &Tree::set_column_title_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_column_title_opentype_feature", "column", "tag"), &Tree::get_column_title_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_column_title_opentype_features", "column"), &Tree::clear_column_title_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_column_title_language", "column", "language"), &Tree::set_column_title_language);
ClassDB::bind_method(D_METHOD("get_column_title_language", "column"), &Tree::get_column_title_language);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 0a8dd3204a..1690e7ac57 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -63,7 +63,6 @@ private:
String text;
String suffix;
Ref<TextLine> text_buf;
- Dictionary opentype_features;
String language;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
@@ -220,10 +219,6 @@ public:
void set_text_direction(int p_column, Control::TextDirection p_text_direction);
Control::TextDirection get_text_direction(int p_column) const;
- void set_opentype_feature(int p_column, const String &p_name, int p_value);
- int get_opentype_feature(int p_column, const String &p_name) const;
- void clear_opentype_features(int p_column);
-
void set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser);
TextServer::StructuredTextParser get_structured_text_bidi_override(int p_column) const;
@@ -429,7 +424,6 @@ private:
bool clip_content = false;
String title;
Ref<TextLine> text_buf;
- Dictionary opentype_features;
String language;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
ColumnInfo() {
@@ -616,6 +610,8 @@ private:
void _go_down();
void _go_up();
+ bool _scroll(bool p_horizontal, float p_pages);
+
protected:
static void _bind_methods();
@@ -666,10 +662,6 @@ public:
void set_column_title_direction(int p_column, Control::TextDirection p_text_direction);
Control::TextDirection get_column_title_direction(int p_column) const;
- void set_column_title_opentype_feature(int p_column, const String &p_name, int p_value);
- int get_column_title_opentype_feature(int p_column, const String &p_name) const;
- void clear_column_title_opentype_features(int p_column);
-
void set_column_title_language(int p_column, const String &p_language);
String get_column_title_language(int p_column) const;
diff --git a/scene/gui/video_stream_player.h b/scene/gui/video_stream_player.h
index d2822a989b..913e7905b6 100644
--- a/scene/gui/video_stream_player.h
+++ b/scene/gui/video_stream_player.h
@@ -64,7 +64,7 @@ class VideoStreamPlayer : public Control {
bool autoplay = false;
float volume = 1.0;
double last_audio_time = 0.0;
- bool expand = true;
+ bool expand = false;
bool loops = false;
int buffering_ms = 500;
int audio_track = 0;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 3dc358a6c2..5e90615ac1 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -658,24 +658,48 @@ void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Tex
RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid);
}
-void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, 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 {
+void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
- p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
+
+ p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_modulate, p_flags, p_direction, p_orientation);
+}
+
+void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_font.is_null());
+
+ p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_flags, p_direction, p_orientation);
}
-void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, real_t 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 {
+void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
ERR_FAIL_COND(p_font.is_null());
- p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_max_lines, p_size, p_modulate, p_outline_size, p_outline_modulate, p_flags);
+
+ p_font->draw_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_size, p_modulate, p_flags, p_direction, p_orientation);
}
-real_t CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const {
- ERR_FAIL_COND_V_MSG(!drawing, 0.f, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
- ERR_FAIL_COND_V(p_font.is_null(), 0.f);
- ERR_FAIL_COND_V(p_char.length() != 1, 0.f);
+void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_font.is_null());
+
+ p_font->draw_multiline_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_size, p_modulate, p_flags, p_direction, p_orientation);
+}
+
+void CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, const Color &p_modulate) const {
+ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_char.length() != 1);
+ ERR_FAIL_COND(p_font.is_null());
+
+ p_font->draw_char(canvas_item, p_pos, p_char[0], p_font_size, p_modulate);
+}
+
+void CanvasItem::draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, int p_size, const Color &p_modulate) const {
+ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_char.length() != 1);
+ ERR_FAIL_COND(p_font.is_null());
- return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], p_size, p_modulate, p_outline_size, p_outline_modulate);
+ p_font->draw_char_outline(canvas_item, p_pos, p_char[0], p_font_size, p_size, p_modulate);
}
void CanvasItem::_notify_transform(CanvasItem *p_node) {
@@ -900,9 +924,12 @@ 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", "alignment", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_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", "alignment", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_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_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "flags", "direction", "orientation"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "font_size", "modulate"), &CanvasItem::draw_char, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)));
+ ClassDB::bind_method(D_METHOD("draw_char_outline", "font", "pos", "char", "font_size", "size", "modulate"), &CanvasItem::draw_char_outline, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 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 ad64f1ab5e..c88878725f 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -235,9 +235,14 @@ 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, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_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, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_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_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+ void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+
+ void draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_size = 1, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+ void draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+
+ void draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
+ void draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size = Font::DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 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/node.cpp b/scene/main/node.cpp
index 545ff68b72..b4701637a4 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -439,9 +439,9 @@ void Node::set_physics_process(bool p_process) {
data.physics_process = p_process;
if (data.physics_process) {
- add_to_group("physics_process", false);
+ add_to_group(SNAME("_physics_process"), false);
} else {
- remove_from_group("physics_process");
+ remove_from_group(SNAME("_physics_process"));
}
}
@@ -457,9 +457,9 @@ void Node::set_physics_process_internal(bool p_process_internal) {
data.physics_process_internal = p_process_internal;
if (data.physics_process_internal) {
- add_to_group("physics_process_internal", false);
+ add_to_group(SNAME("_physics_process_internal"), false);
} else {
- remove_from_group("physics_process_internal");
+ remove_from_group(SNAME("_physics_process_internal"));
}
}
@@ -770,9 +770,9 @@ void Node::set_process(bool p_process) {
data.process = p_process;
if (data.process) {
- add_to_group("process", false);
+ add_to_group(SNAME("_process"), false);
} else {
- remove_from_group("process");
+ remove_from_group(SNAME("_process"));
}
}
@@ -788,9 +788,9 @@ void Node::set_process_internal(bool p_process_internal) {
data.process_internal = p_process_internal;
if (data.process_internal) {
- add_to_group("process_internal", false);
+ add_to_group(SNAME("_process_internal"), false);
} else {
- remove_from_group("process_internal");
+ remove_from_group(SNAME("_process_internal"));
}
}
@@ -807,19 +807,19 @@ void Node::set_process_priority(int p_priority) {
}
if (is_processing()) {
- data.tree->make_group_changed("process");
+ data.tree->make_group_changed(SNAME("_process"));
}
if (is_processing_internal()) {
- data.tree->make_group_changed("process_internal");
+ data.tree->make_group_changed(SNAME("_process_internal"));
}
if (is_physics_processing()) {
- data.tree->make_group_changed("physics_process");
+ data.tree->make_group_changed(SNAME("_physics_process"));
}
if (is_physics_processing_internal()) {
- data.tree->make_group_changed("physics_process_internal");
+ data.tree->make_group_changed(SNAME("_physics_process_internal"));
}
}
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 18f69ecc82..a76c00efcb 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -412,9 +412,9 @@ bool SceneTree::physics_process(double p_time) {
emit_signal(SNAME("physics_frame"));
- _notify_group_pause(SNAME("physics_process_internal"), Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ _notify_group_pause(SNAME("_physics_process_internal"), Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
call_group(SNAME("_picking_viewports"), SNAME("_process_picking"));
- _notify_group_pause(SNAME("physics_process"), Node::NOTIFICATION_PHYSICS_PROCESS);
+ _notify_group_pause(SNAME("_physics_process"), Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
@@ -449,8 +449,8 @@ bool SceneTree::process(double p_time) {
flush_transform_notifications();
- _notify_group_pause(SNAME("process_internal"), Node::NOTIFICATION_INTERNAL_PROCESS);
- _notify_group_pause(SNAME("process"), Node::NOTIFICATION_PROCESS);
+ _notify_group_pause(SNAME("_process_internal"), Node::NOTIFICATION_INTERNAL_PROCESS);
+ _notify_group_pause(SNAME("_process"), Node::NOTIFICATION_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1ad011f867..0080e899c3 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -219,7 +219,7 @@ void Viewport::_sub_window_update(Window *p_window) {
int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_offset"));
int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_offset"));
- TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size);
title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
title_text.set_direction(p_window->is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
int x = (r.size.width - title_text.get_size().x) / 2;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index f70d57291f..5c5b60df63 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -143,6 +143,7 @@
#include "scene/resources/animation_library.h"
#include "scene/resources/audio_stream_sample.h"
#include "scene/resources/bit_map.h"
+#include "scene/resources/bone_map.h"
#include "scene/resources/box_shape_3d.h"
#include "scene/resources/camera_effects.h"
#include "scene/resources/capsule_shape_2d.h"
@@ -189,6 +190,7 @@
#include "scene/resources/skeleton_modification_3d_twoboneik.h"
#include "scene/resources/skeleton_modification_stack_2d.h"
#include "scene/resources/skeleton_modification_stack_3d.h"
+#include "scene/resources/skeleton_profile.h"
#include "scene/resources/sky.h"
#include "scene/resources/sky_material.h"
#include "scene/resources/sphere_shape_3d.h"
@@ -851,8 +853,11 @@ void register_scene_types() {
GDREGISTER_CLASS(Animation);
GDREGISTER_CLASS(AnimationLibrary);
- GDREGISTER_CLASS(FontData);
- GDREGISTER_CLASS(Font);
+
+ GDREGISTER_ABSTRACT_CLASS(Font);
+ GDREGISTER_CLASS(FontFile);
+ GDREGISTER_CLASS(FontVariation);
+
GDREGISTER_CLASS(Curve);
GDREGISTER_CLASS(SceneReplicationConfig);
@@ -871,6 +876,10 @@ void register_scene_types() {
GDREGISTER_CLASS(BitMap);
GDREGISTER_CLASS(Gradient);
+ GDREGISTER_CLASS(SkeletonProfile);
+ GDREGISTER_CLASS(SkeletonProfileHumanoid);
+ GDREGISTER_CLASS(BoneMap);
+
OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(AudioStreamPlayer);
@@ -915,9 +924,9 @@ void register_scene_types() {
ClassDB::add_compatibility_class("AnimationTreePlayer", "AnimationTree");
ClassDB::add_compatibility_class("BakedLightmap", "LightmapGI");
ClassDB::add_compatibility_class("BakedLightmapData", "LightmapGIData");
- ClassDB::add_compatibility_class("BitmapFont", "Font");
- ClassDB::add_compatibility_class("DynamicFont", "Font");
- ClassDB::add_compatibility_class("DynamicFontData", "FontData");
+ ClassDB::add_compatibility_class("BitmapFont", "FontFile");
+ ClassDB::add_compatibility_class("DynamicFont", "FontFile");
+ ClassDB::add_compatibility_class("DynamicFontData", "FontFile");
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite");
@@ -1107,7 +1116,7 @@ void initialize_theme() {
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", "");
- ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
+ ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp
new file mode 100644
index 0000000000..ce030934fa
--- /dev/null
+++ b/scene/resources/bone_map.cpp
@@ -0,0 +1,172 @@
+/*************************************************************************/
+/* bone_map.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "bone_map.h"
+
+bool BoneMap::_set(const StringName &p_path, const Variant &p_value) {
+ String path = p_path;
+ if (path.begins_with("bone_map/")) {
+ String which = path.get_slicec('/', 1);
+ set_skeleton_bone_name(which, p_value);
+ return true;
+ }
+ return true;
+}
+
+bool BoneMap::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+ if (path.begins_with("bone_map/")) {
+ String which = path.get_slicec('/', 1);
+ r_ret = get_skeleton_bone_name(which);
+ return true;
+ }
+ return true;
+}
+
+Ref<SkeletonProfile> BoneMap::get_profile() const {
+ return profile;
+}
+
+void BoneMap::set_profile(const Ref<SkeletonProfile> &p_profile) {
+ bool is_changed = profile != p_profile;
+ if (is_changed) {
+ if (!profile.is_null() && profile->is_connected("profile_updated", callable_mp(this, &BoneMap::_update_profile))) {
+ profile->disconnect("profile_updated", callable_mp(this, &BoneMap::_update_profile));
+ }
+ profile = p_profile;
+ if (!profile.is_null()) {
+ profile->connect("profile_updated", callable_mp(this, &BoneMap::_update_profile));
+ }
+ _update_profile();
+ }
+ notify_property_list_changed();
+}
+
+StringName BoneMap::get_skeleton_bone_name(StringName p_profile_bone_name) const {
+ ERR_FAIL_COND_V(!bone_map.has(p_profile_bone_name), StringName());
+ return bone_map.get(p_profile_bone_name);
+}
+
+void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) {
+ ERR_FAIL_COND(!bone_map.has(p_profile_bone_name));
+ bone_map.insert(p_profile_bone_name, p_skeleton_bone_name);
+ emit_signal("bone_map_updated");
+}
+
+StringName BoneMap::find_profile_bone_name(StringName p_skeleton_bone_name) const {
+ StringName profile_bone_name = StringName();
+ HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
+ while (E) {
+ if (E->value == p_skeleton_bone_name) {
+ profile_bone_name = E->key;
+ break;
+ }
+ ++E;
+ }
+ return profile_bone_name;
+}
+
+int BoneMap::get_skeleton_bone_name_count(const StringName p_skeleton_bone_name) const {
+ int count = 0;
+ HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
+ while (E) {
+ if (E->value == p_skeleton_bone_name) {
+ ++count;
+ }
+ ++E;
+ }
+ return count;
+}
+
+void BoneMap::_update_profile() {
+ _validate_bone_map();
+ emit_signal("profile_updated");
+}
+
+void BoneMap::_validate_bone_map() {
+ Ref<SkeletonProfile> current_profile = get_profile();
+ if (current_profile.is_valid()) {
+ // Insert missing profile bones into bone map.
+ int len = current_profile->get_bone_size();
+ StringName profile_bone_name;
+ for (int i = 0; i < len; i++) {
+ profile_bone_name = current_profile->get_bone_name(i);
+ if (!bone_map.has(profile_bone_name)) {
+ bone_map.insert(profile_bone_name, StringName());
+ }
+ }
+ // Remove bones that do not exist in the profile from the map.
+ Vector<StringName> delete_bones;
+ StringName k;
+ HashMap<StringName, StringName>::ConstIterator E = bone_map.begin();
+ while (E) {
+ k = E->key;
+ if (!current_profile->has_bone(k)) {
+ delete_bones.push_back(k);
+ }
+ ++E;
+ }
+ len = delete_bones.size();
+ for (int i = 0; i < len; i++) {
+ bone_map.erase(delete_bones[i]);
+ }
+ } else {
+ bone_map.clear();
+ }
+ emit_signal("retarget_option_updated");
+}
+
+void BoneMap::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_profile"), &BoneMap::get_profile);
+ ClassDB::bind_method(D_METHOD("set_profile", "profile"), &BoneMap::set_profile);
+
+ ClassDB::bind_method(D_METHOD("get_skeleton_bone_name", "profile_bone_name"), &BoneMap::get_skeleton_bone_name);
+ ClassDB::bind_method(D_METHOD("set_skeleton_bone_name", "profile_bone_name", "skeleton_bone_name"), &BoneMap::set_skeleton_bone_name);
+
+ ClassDB::bind_method(D_METHOD("find_profile_bone_name", "skeleton_bone_name"), &BoneMap::find_profile_bone_name);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "profile", PROPERTY_HINT_RESOURCE_TYPE, "SkeletonProfile"), "set_profile", "get_profile");
+
+ ADD_SIGNAL(MethodInfo("bone_map_updated"));
+ ADD_SIGNAL(MethodInfo("profile_updated"));
+}
+
+void BoneMap::_validate_property(PropertyInfo &property) const {
+ //
+}
+
+BoneMap::BoneMap() {
+ _validate_bone_map();
+}
+
+BoneMap::~BoneMap() {
+}
+
+//////////////////////////////////////
diff --git a/editor/plugins/font_editor_plugin.h b/scene/resources/bone_map.h
index 3f0700d880..4b7928015d 100644
--- a/editor/plugins/font_editor_plugin.h
+++ b/scene/resources/bone_map.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* font_editor_plugin.h */
+/* bone_map.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,50 +28,42 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef FONT_EDITOR_PLUGIN_H
-#define FONT_EDITOR_PLUGIN_H
+#ifndef BONE_MAP_H
+#define BONE_MAP_H
-#include "editor/editor_plugin.h"
-#include "scene/resources/font.h"
-#include "scene/resources/text_line.h"
+#include "skeleton_profile.h"
-class FontDataPreview : public Control {
- GDCLASS(FontDataPreview, Control);
+class BoneMap : public Resource {
+ GDCLASS(BoneMap, Resource);
+
+ Ref<SkeletonProfile> profile;
+ HashMap<StringName, StringName> bone_map;
+
+ void _update_profile();
+ void _validate_bone_map();
protected:
- void _notification(int p_what);
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ virtual void _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
- Ref<TextLine> line;
-
public:
- virtual Size2 get_minimum_size() const override;
+ int get_profile_type() const;
+ void set_profile_type(const int p_profile_type);
- void set_data(const Ref<FontData> &p_data);
+ Ref<SkeletonProfile> get_profile() const;
+ void set_profile(const Ref<SkeletonProfile> &p_profile);
- FontDataPreview();
-};
+ int get_skeleton_bone_name_count(const StringName p_skeleton_bone_name) const;
-/*************************************************************************/
-
-class EditorInspectorPluginFont : public EditorInspectorPlugin {
- GDCLASS(EditorInspectorPluginFont, EditorInspectorPlugin);
+ StringName get_skeleton_bone_name(StringName p_profile_bone_name) const;
+ void set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name);
-public:
- virtual bool can_handle(Object *p_object) override;
- virtual void parse_begin(Object *p_object) override;
- virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
-};
-
-/*************************************************************************/
-
-class FontEditorPlugin : public EditorPlugin {
- GDCLASS(FontEditorPlugin, EditorPlugin);
-
-public:
- FontEditorPlugin();
+ StringName find_profile_bone_name(StringName p_skeleton_bone_name) const;
- virtual String get_name() const override { return "Font"; }
+ BoneMap();
+ ~BoneMap();
};
-#endif // FONT_EDITOR_PLUGIN_H
+#endif // BONE_MAP_H
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 401aeb4889..520a0a04ed 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -76,7 +76,6 @@ static Ref<StyleBoxFlat> sb_expand(Ref<StyleBoxFlat> p_sbox, float p_left, float
// See also `editor_generate_icon()` in `editor/editor_themes.cpp`.
static Ref<ImageTexture> generate_icon(int p_index) {
- Ref<ImageTexture> icon = memnew(ImageTexture);
Ref<Image> img = memnew(Image);
#ifdef MODULE_SVG_ENABLED
@@ -87,9 +86,8 @@ static Ref<ImageTexture> generate_icon(int p_index) {
ImageLoaderSVG img_loader;
img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, false);
#endif
- icon->create_from_image(img);
- return icon;
+ return ImageTexture::create_from_image(img);
}
static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
@@ -467,6 +465,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("completion_selected_color", "CodeEdit", Color(0.26, 0.26, 0.27));
theme->set_color("completion_existing_color", "CodeEdit", Color(0.87, 0.87, 0.87, 0.13));
theme->set_color("completion_scroll_color", "CodeEdit", control_font_pressed_color * Color(1, 1, 1, 0.29));
+ theme->set_color("completion_scroll_hovered_color", "CodeEdit", control_font_pressed_color * Color(1, 1, 1, 0.4));
theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67));
theme->set_color("font_color", "CodeEdit", control_font_color);
theme->set_color("font_selected_color", "CodeEdit", Color(0, 0, 0));
@@ -917,8 +916,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_stylebox("panel", "TooltipPanel",
make_flat_stylebox(Color(0, 0, 0, 0.5), 2 * default_margin, 0.5 * default_margin, 2 * default_margin, 0.5 * default_margin));
- theme->set_font("font", "TooltipLabel", Ref<Font>());
theme->set_font_size("font_size", "TooltipLabel", -1);
+ theme->set_font("font", "TooltipLabel", Ref<Font>());
theme->set_color("font_color", "TooltipLabel", control_font_color);
theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0));
@@ -938,7 +937,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_font("italics_font", "RichTextLabel", italics_font);
theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
-
theme->set_font_size("normal_font_size", "RichTextLabel", -1);
theme->set_font_size("bold_font_size", "RichTextLabel", -1);
theme->set_font_size("italics_font_size", "RichTextLabel", -1);
@@ -1033,9 +1031,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
- Ref<Font> bold_font;
- Ref<Font> bold_italics_font;
- Ref<Font> italics_font;
+ Ref<FontVariation> bold_font;
+ Ref<FontVariation> bold_italics_font;
+ Ref<FontVariation> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) {
@@ -1045,48 +1043,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
// Use the default DynamicFont (separate from the editor font).
// The default DynamicFont is chosen to have a small file size since it's
// embedded in both editor and export template binaries.
- Ref<Font> dynamic_font;
+ Ref<FontFile> dynamic_font;
dynamic_font.instantiate();
-
- Ref<FontData> dynamic_font_data;
- dynamic_font_data.instantiate();
- dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
- dynamic_font_data->set_subpixel_positioning(p_font_subpixel);
- dynamic_font_data->set_hinting(p_font_hinting);
- dynamic_font_data->set_antialiased(p_font_antialiased);
- dynamic_font_data->set_multichannel_signed_distance_field(p_font_msdf);
- dynamic_font_data->set_generate_mipmaps(p_font_generate_mipmaps);
-
- dynamic_font->add_data(dynamic_font_data);
+ dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
+ dynamic_font->set_subpixel_positioning(p_font_subpixel);
+ dynamic_font->set_hinting(p_font_hinting);
+ dynamic_font->set_antialiased(p_font_antialiased);
+ dynamic_font->set_multichannel_signed_distance_field(p_font_msdf);
+ dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps);
default_font = dynamic_font;
}
if (default_font.is_valid()) {
bold_font.instantiate();
- for (int i = 0; i < default_font->get_data_count(); i++) {
- Ref<FontData> data = default_font->get_data(i)->duplicate();
- // Try to match OpenSans ExtraBold.
- data->set_embolden(1.2);
- bold_font->add_data(data);
- }
+ bold_font->set_base_font(default_font);
+ bold_font->set_variation_embolden(1.2);
bold_italics_font.instantiate();
- for (int i = 0; i < default_font->get_data_count(); i++) {
- Ref<FontData> data = default_font->get_data(i)->duplicate();
- // Try to match OpenSans ExtraBold Italic.
- data->set_embolden(1.2);
- data->set_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
- bold_italics_font->add_data(data);
- }
+ bold_italics_font->set_base_font(default_font);
+ bold_italics_font->set_variation_embolden(1.2);
+ bold_italics_font->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
italics_font.instantiate();
- for (int i = 0; i < default_font->get_data_count(); i++) {
- Ref<FontData> data = default_font->get_data(i)->duplicate();
- // Try to match OpenSans Italic.
- data->set_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
- italics_font->add_data(data);
- }
+ italics_font->set_base_font(default_font);
+ italics_font->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
}
fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 46f23424dd..6053d27ef7 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -30,6 +30,7 @@
#include "font.h"
+#include "core/core_string_names.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/string/translation.h"
@@ -37,439 +38,539 @@
#include "core/templates/hashfuncs.h"
#include "scene/resources/text_line.h"
#include "scene/resources/text_paragraph.h"
+#include "scene/resources/theme.h"
-_FORCE_INLINE_ void FontData::_clear_cache() {
- for (int i = 0; i < cache.size(); i++) {
- if (cache[i].is_valid()) {
- TS->free_rid(cache[i]);
- cache.write[i] = RID();
- }
- }
-}
+/*************************************************************************/
+/* Font */
+/*************************************************************************/
-_FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
- if (unlikely(p_cache_index >= cache.size())) {
- cache.resize(p_cache_index + 1);
- }
- if (unlikely(!cache[p_cache_index].is_valid())) {
- cache.write[p_cache_index] = TS->create_font();
- TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
- TS->font_set_face_index(cache[p_cache_index], face_index);
- TS->font_set_antialiased(cache[p_cache_index], antialiased);
- TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
- TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
- TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range);
- TS->font_set_msdf_size(cache[p_cache_index], msdf_size);
- TS->font_set_fixed_size(cache[p_cache_index], fixed_size);
- TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
- TS->font_set_hinting(cache[p_cache_index], hinting);
- TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
- TS->font_set_embolden(cache[p_cache_index], embolden);
- TS->font_set_transform(cache[p_cache_index], transform);
- TS->font_set_oversampling(cache[p_cache_index], oversampling);
- }
-}
+void Font::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_fallbacks", "fallbacks"), &Font::set_fallbacks);
+ ClassDB::bind_method(D_METHOD("get_fallbacks"), &Font::get_fallbacks);
-void FontData::_bind_methods() {
- ClassDB::bind_method(D_METHOD("load_bitmap_font", "path"), &FontData::load_bitmap_font);
- ClassDB::bind_method(D_METHOD("load_dynamic_font", "path"), &FontData::load_dynamic_font);
+ // Output.
+ ClassDB::bind_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform"), &Font::find_variation, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("get_rids"), &Font::get_rids);
- ClassDB::bind_method(D_METHOD("set_data", "data"), &FontData::set_data);
- ClassDB::bind_method(D_METHOD("get_data"), &FontData::get_data);
+ // Font metrics.
+ ClassDB::bind_method(D_METHOD("get_height", "font_size"), &Font::get_height, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_ascent", "font_size"), &Font::get_ascent, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_descent", "font_size"), &Font::get_descent, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_underline_position", "font_size"), &Font::get_underline_position, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_underline_thickness", "font_size"), &Font::get_underline_thickness, DEFVAL(DEFAULT_FONT_SIZE));
- ClassDB::bind_method(D_METHOD("set_face_index", "face_index"), &FontData::set_face_index);
- ClassDB::bind_method(D_METHOD("get_face_index"), &FontData::get_face_index);
+ ClassDB::bind_method(D_METHOD("get_font_name"), &Font::get_font_name);
+ ClassDB::bind_method(D_METHOD("get_font_style_name"), &Font::get_font_style_name);
+ ClassDB::bind_method(D_METHOD("get_font_style"), &Font::get_font_style);
- ClassDB::bind_method(D_METHOD("get_face_count"), &FontData::get_face_count);
+ ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
+ ClassDB::bind_method(D_METHOD("get_opentype_features"), &Font::get_opentype_features);
- ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased);
- ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased);
+ // Drawing string.
+ ClassDB::bind_method(D_METHOD("set_cache_capacity", "single_line", "multi_line"), &Font::set_cache_capacity);
- ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontData::set_generate_mipmaps);
- ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontData::get_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontData::set_font_name);
- ClassDB::bind_method(D_METHOD("get_font_name"), &FontData::get_font_name);
+ ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "flags", "direction", "orientation"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "flags", "direction", "orientation"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontData::set_font_style_name);
- ClassDB::bind_method(D_METHOD("get_font_style_name"), &FontData::get_font_style_name);
+ ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "flags", "direction", "orientation"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "flags", "direction", "orientation"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
- ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontData::set_font_style);
- ClassDB::bind_method(D_METHOD("get_font_style"), &FontData::get_font_style);
+ // Drawing char.
+ ClassDB::bind_method(D_METHOD("get_char_size", "char"), &Font::get_char_size);
+ ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "modulate"), &Font::draw_char, DEFVAL(Color(1.0, 1.0, 1.0)));
+ ClassDB::bind_method(D_METHOD("draw_char_outline", "canvas_item", "pos", "char", "size", "modulate"), &Font::draw_char_outline, DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)));
- ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &FontData::set_multichannel_signed_distance_field);
- ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &FontData::is_multichannel_signed_distance_field);
+ // Helper functions.
+ ClassDB::bind_method(D_METHOD("has_char", "char"), &Font::has_char);
+ ClassDB::bind_method(D_METHOD("get_supported_chars"), &Font::get_supported_chars);
- ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "msdf_pixel_range"), &FontData::set_msdf_pixel_range);
- ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &FontData::get_msdf_pixel_range);
+ ClassDB::bind_method(D_METHOD("is_language_supported", "language"), &Font::is_language_supported);
+ ClassDB::bind_method(D_METHOD("is_script_supported", "script"), &Font::is_script_supported);
- ClassDB::bind_method(D_METHOD("set_msdf_size", "msdf_size"), &FontData::set_msdf_size);
- ClassDB::bind_method(D_METHOD("get_msdf_size"), &FontData::get_msdf_size);
+ ClassDB::bind_method(D_METHOD("get_supported_feature_list"), &Font::get_supported_feature_list);
+ ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &Font::get_supported_variation_list);
+ ClassDB::bind_method(D_METHOD("get_face_count"), &Font::get_face_count);
+}
- ClassDB::bind_method(D_METHOD("set_fixed_size", "fixed_size"), &FontData::set_fixed_size);
- ClassDB::bind_method(D_METHOD("get_fixed_size"), &FontData::get_fixed_size);
+void Font::_update_rids_fb(const Ref<Font> &p_f, int p_depth) const {
+ ERR_FAIL_COND(p_depth > MAX_FALLBACK_DEPTH);
+ if (p_f.is_valid()) {
+ RID rid = p_f->_get_rid();
+ if (rid.is_valid()) {
+ rids.push_back(rid);
+ }
+ const TypedArray<Font> &_fallbacks = p_f->get_fallbacks();
+ for (int i = 0; i < _fallbacks.size(); i++) {
+ _update_rids_fb(_fallbacks[i], p_depth + 1);
+ }
+ }
+}
- ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &FontData::set_force_autohinter);
- ClassDB::bind_method(D_METHOD("is_force_autohinter"), &FontData::is_force_autohinter);
+void Font::_update_rids() const {
+ rids.clear();
+ _update_rids_fb(const_cast<Font *>(this), 0);
+ dirty_rids = false;
+}
- ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &FontData::set_hinting);
- ClassDB::bind_method(D_METHOD("get_hinting"), &FontData::get_hinting);
+void Font::_invalidate_rids() {
+ rids.clear();
+ dirty_rids = true;
- ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
- ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
+ cache.clear();
+ cache_wrap.clear();
- ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
- ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
+ emit_changed();
+}
- ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform);
- ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
+bool Font::_is_cyclic(const Ref<Font> &p_f, int p_depth) const {
+ ERR_FAIL_COND_V(p_depth > MAX_FALLBACK_DEPTH, false);
+ if (p_f.is_null()) {
+ return false;
+ }
+ for (int i = 0; i < p_f->fallbacks.size(); i++) {
+ const Ref<Font> &f = p_f->fallbacks[i];
+ if (f == this) {
+ return true;
+ }
+ return _is_cyclic(f, p_depth + 1);
+ }
+ return false;
+}
- ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
- ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
+void Font::reset_state() {
+ _invalidate_rids();
+}
- ClassDB::bind_method(D_METHOD("find_cache", "variation_coordinates"), &FontData::find_cache);
+// Fallbacks.
+void Font::set_fallbacks(const TypedArray<Font> &p_fallbacks) {
+ ERR_FAIL_COND(_is_cyclic(this, 0));
+ for (int i = 0; i < fallbacks.size(); i++) {
+ Ref<Font> f = fallbacks[i];
+ if (f.is_valid()) {
+ f->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Font::_invalidate_rids));
+ }
+ }
+ fallbacks = p_fallbacks;
+ for (int i = 0; i < fallbacks.size(); i++) {
+ Ref<Font> f = fallbacks[i];
+ if (f.is_valid()) {
+ f->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ }
+ _invalidate_rids();
+}
- ClassDB::bind_method(D_METHOD("get_cache_count"), &FontData::get_cache_count);
- ClassDB::bind_method(D_METHOD("clear_cache"), &FontData::clear_cache);
- ClassDB::bind_method(D_METHOD("remove_cache", "cache_index"), &FontData::remove_cache);
+TypedArray<Font> Font::get_fallbacks() const {
+ return fallbacks;
+}
- ClassDB::bind_method(D_METHOD("get_size_cache_list", "cache_index"), &FontData::get_size_cache_list);
- ClassDB::bind_method(D_METHOD("clear_size_cache", "cache_index"), &FontData::clear_size_cache);
- ClassDB::bind_method(D_METHOD("remove_size_cache", "cache_index", "size"), &FontData::remove_size_cache);
+// Output.
+TypedArray<RID> Font::get_rids() const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ return rids;
+}
- ClassDB::bind_method(D_METHOD("set_variation_coordinates", "cache_index", "variation_coordinates"), &FontData::set_variation_coordinates);
- ClassDB::bind_method(D_METHOD("get_variation_coordinates", "cache_index"), &FontData::get_variation_coordinates);
+// Drawing string.
+real_t Font::get_height(int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ real_t ret = 0.f;
+ for (int i = 0; i < rids.size(); i++) {
+ ret = MAX(ret, TS->font_get_ascent(rids[i], p_font_size) + TS->font_get_descent(rids[i], p_font_size));
+ }
+ return ret + get_spacing(TextServer::SPACING_BOTTOM) + get_spacing(TextServer::SPACING_TOP);
+}
- ClassDB::bind_method(D_METHOD("set_ascent", "cache_index", "size", "ascent"), &FontData::set_ascent);
- ClassDB::bind_method(D_METHOD("get_ascent", "cache_index", "size"), &FontData::get_ascent);
+real_t Font::get_ascent(int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ real_t ret = 0.f;
+ for (int i = 0; i < rids.size(); i++) {
+ ret = MAX(ret, TS->font_get_ascent(rids[i], p_font_size));
+ }
+ return ret + get_spacing(TextServer::SPACING_TOP);
+}
+
+real_t Font::get_descent(int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ real_t ret = 0.f;
+ for (int i = 0; i < rids.size(); i++) {
+ ret = MAX(ret, TS->font_get_descent(rids[i], p_font_size));
+ }
+ return ret + get_spacing(TextServer::SPACING_BOTTOM);
+}
+
+real_t Font::get_underline_position(int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ real_t ret = 0.f;
+ for (int i = 0; i < rids.size(); i++) {
+ ret = MAX(ret, TS->font_get_underline_position(rids[i], p_font_size));
+ }
+ return ret + get_spacing(TextServer::SPACING_TOP);
+}
- ClassDB::bind_method(D_METHOD("set_descent", "cache_index", "size", "descent"), &FontData::set_descent);
- ClassDB::bind_method(D_METHOD("get_descent", "cache_index", "size"), &FontData::get_descent);
+real_t Font::get_underline_thickness(int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ real_t ret = 0.f;
+ for (int i = 0; i < rids.size(); i++) {
+ ret = MAX(ret, TS->font_get_underline_thickness(rids[i], p_font_size));
+ }
+ return ret;
+}
- ClassDB::bind_method(D_METHOD("set_underline_position", "cache_index", "size", "underline_position"), &FontData::set_underline_position);
- ClassDB::bind_method(D_METHOD("get_underline_position", "cache_index", "size"), &FontData::get_underline_position);
+String Font::get_font_name() const {
+ return TS->font_get_name(_get_rid());
+}
- ClassDB::bind_method(D_METHOD("set_underline_thickness", "cache_index", "size", "underline_thickness"), &FontData::set_underline_thickness);
- ClassDB::bind_method(D_METHOD("get_underline_thickness", "cache_index", "size"), &FontData::get_underline_thickness);
+String Font::get_font_style_name() const {
+ return TS->font_get_style_name(_get_rid());
+}
- ClassDB::bind_method(D_METHOD("set_scale", "cache_index", "size", "scale"), &FontData::set_scale);
- ClassDB::bind_method(D_METHOD("get_scale", "cache_index", "size"), &FontData::get_scale);
+uint32_t Font::get_font_style() const {
+ return TS->font_get_style(_get_rid());
+}
- ClassDB::bind_method(D_METHOD("set_spacing", "cache_index", "size", "spacing_type", "value"), &FontData::set_spacing);
- ClassDB::bind_method(D_METHOD("get_spacing", "cache_index", "size", "spacing_type"), &FontData::get_spacing);
+Dictionary Font::get_opentype_features() const {
+ return Dictionary();
+}
+
+// Drawing string.
+void Font::set_cache_capacity(int p_single_line, int p_multi_line) {
+ cache.set_capacity(p_single_line);
+ cache_wrap.set_capacity(p_multi_line);
+}
- ClassDB::bind_method(D_METHOD("get_texture_count", "cache_index", "size"), &FontData::get_texture_count);
- ClassDB::bind_method(D_METHOD("clear_textures", "cache_index", "size"), &FontData::clear_textures);
- ClassDB::bind_method(D_METHOD("remove_texture", "cache_index", "size", "texture_index"), &FontData::remove_texture);
+Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
+ }
- ClassDB::bind_method(D_METHOD("set_texture_image", "cache_index", "size", "texture_index", "image"), &FontData::set_texture_image);
- ClassDB::bind_method(D_METHOD("get_texture_image", "cache_index", "size", "texture_index"), &FontData::get_texture_image);
+ Ref<TextLine> buffer;
+ if (cache.has(hash)) {
+ buffer = cache.get(hash);
+ } else {
+ buffer.instantiate();
+ buffer->set_direction(p_direction);
+ buffer->set_orientation(p_orientation);
+ buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ cache.insert(hash, buffer);
+ }
+ return buffer->get_size();
+}
+
+Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
+
+ Ref<TextParagraph> lines_buffer;
+ if (cache_wrap.has(hash)) {
+ lines_buffer = cache_wrap.get(hash);
+ } else {
+ lines_buffer.instantiate();
+ lines_buffer->set_direction(p_direction);
+ lines_buffer->set_orientation(p_orientation);
+ lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ lines_buffer->set_width(p_width);
+ lines_buffer->set_flags(p_flags);
+ cache_wrap.insert(hash, lines_buffer);
+ }
+
+ lines_buffer->set_alignment(p_alignment);
+ lines_buffer->set_max_lines_visible(p_max_lines);
+
+ return lines_buffer->get_size();
+}
+
+void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ }
+
+ Ref<TextLine> buffer;
+ if (cache.has(hash)) {
+ buffer = cache.get(hash);
+ } else {
+ buffer.instantiate();
+ buffer->set_direction(p_direction);
+ buffer->set_orientation(p_orientation);
+ buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ cache.insert(hash, buffer);
+ }
- ClassDB::bind_method(D_METHOD("set_texture_offsets", "cache_index", "size", "texture_index", "offset"), &FontData::set_texture_offsets);
- ClassDB::bind_method(D_METHOD("get_texture_offsets", "cache_index", "size", "texture_index"), &FontData::get_texture_offsets);
+ Vector2 ofs = p_pos;
+ if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.y -= buffer->get_line_ascent();
+ } else {
+ ofs.x -= buffer->get_line_ascent();
+ }
- ClassDB::bind_method(D_METHOD("get_glyph_list", "cache_index", "size"), &FontData::get_glyph_list);
- ClassDB::bind_method(D_METHOD("clear_glyphs", "cache_index", "size"), &FontData::clear_glyphs);
- ClassDB::bind_method(D_METHOD("remove_glyph", "cache_index", "size", "glyph"), &FontData::remove_glyph);
+ buffer->set_width(p_width);
+ buffer->set_horizontal_alignment(p_alignment);
+ buffer->set_flags(p_flags);
- ClassDB::bind_method(D_METHOD("set_glyph_advance", "cache_index", "size", "glyph", "advance"), &FontData::set_glyph_advance);
- ClassDB::bind_method(D_METHOD("get_glyph_advance", "cache_index", "size", "glyph"), &FontData::get_glyph_advance);
+ buffer->draw(p_canvas_item, ofs, p_modulate);
+}
- ClassDB::bind_method(D_METHOD("set_glyph_offset", "cache_index", "size", "glyph", "offset"), &FontData::set_glyph_offset);
- ClassDB::bind_method(D_METHOD("get_glyph_offset", "cache_index", "size", "glyph"), &FontData::get_glyph_offset);
+void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
- ClassDB::bind_method(D_METHOD("set_glyph_size", "cache_index", "size", "glyph", "gl_size"), &FontData::set_glyph_size);
- ClassDB::bind_method(D_METHOD("get_glyph_size", "cache_index", "size", "glyph"), &FontData::get_glyph_size);
+ Ref<TextParagraph> lines_buffer;
+ if (cache_wrap.has(hash)) {
+ lines_buffer = cache_wrap.get(hash);
+ } else {
+ lines_buffer.instantiate();
+ lines_buffer->set_direction(p_direction);
+ lines_buffer->set_orientation(p_orientation);
+ lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ lines_buffer->set_width(p_width);
+ lines_buffer->set_flags(p_flags);
+ cache_wrap.insert(hash, lines_buffer);
+ }
- ClassDB::bind_method(D_METHOD("set_glyph_uv_rect", "cache_index", "size", "glyph", "uv_rect"), &FontData::set_glyph_uv_rect);
- ClassDB::bind_method(D_METHOD("get_glyph_uv_rect", "cache_index", "size", "glyph"), &FontData::get_glyph_uv_rect);
+ Vector2 ofs = p_pos;
+ if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.y -= lines_buffer->get_line_ascent(0);
+ } else {
+ ofs.x -= lines_buffer->get_line_ascent(0);
+ }
- ClassDB::bind_method(D_METHOD("set_glyph_texture_idx", "cache_index", "size", "glyph", "texture_idx"), &FontData::set_glyph_texture_idx);
- ClassDB::bind_method(D_METHOD("get_glyph_texture_idx", "cache_index", "size", "glyph"), &FontData::get_glyph_texture_idx);
+ lines_buffer->set_alignment(p_alignment);
+ lines_buffer->set_max_lines_visible(p_max_lines);
- ClassDB::bind_method(D_METHOD("get_kerning_list", "cache_index", "size"), &FontData::get_kerning_list);
- ClassDB::bind_method(D_METHOD("clear_kerning_map", "cache_index", "size"), &FontData::clear_kerning_map);
- ClassDB::bind_method(D_METHOD("remove_kerning", "cache_index", "size", "glyph_pair"), &FontData::remove_kerning);
+ lines_buffer->draw(p_canvas_item, ofs, p_modulate);
+}
- ClassDB::bind_method(D_METHOD("set_kerning", "cache_index", "size", "glyph_pair", "kerning"), &FontData::set_kerning);
- ClassDB::bind_method(D_METHOD("get_kerning", "cache_index", "size", "glyph_pair"), &FontData::get_kerning);
+void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ }
- ClassDB::bind_method(D_METHOD("render_range", "cache_index", "size", "start", "end"), &FontData::render_range);
- ClassDB::bind_method(D_METHOD("render_glyph", "cache_index", "size", "index"), &FontData::render_glyph);
+ Ref<TextLine> buffer;
+ if (cache.has(hash)) {
+ buffer = cache.get(hash);
+ } else {
+ buffer.instantiate();
+ buffer->set_direction(p_direction);
+ buffer->set_orientation(p_orientation);
+ buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ cache.insert(hash, buffer);
+ }
- ClassDB::bind_method(D_METHOD("get_cache_rid", "cache_index"), &FontData::get_cache_rid);
+ Vector2 ofs = p_pos;
+ if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.y -= buffer->get_line_ascent();
+ } else {
+ ofs.x -= buffer->get_line_ascent();
+ }
- ClassDB::bind_method(D_METHOD("is_language_supported", "language"), &FontData::is_language_supported);
- ClassDB::bind_method(D_METHOD("set_language_support_override", "language", "supported"), &FontData::set_language_support_override);
- ClassDB::bind_method(D_METHOD("get_language_support_override", "language"), &FontData::get_language_support_override);
- ClassDB::bind_method(D_METHOD("remove_language_support_override", "language"), &FontData::remove_language_support_override);
- ClassDB::bind_method(D_METHOD("get_language_support_overrides"), &FontData::get_language_support_overrides);
+ buffer->set_width(p_width);
+ buffer->set_horizontal_alignment(p_alignment);
+ buffer->set_flags(p_flags);
- ClassDB::bind_method(D_METHOD("is_script_supported", "script"), &FontData::is_script_supported);
- ClassDB::bind_method(D_METHOD("set_script_support_override", "script", "supported"), &FontData::set_script_support_override);
- ClassDB::bind_method(D_METHOD("get_script_support_override", "script"), &FontData::get_script_support_override);
- ClassDB::bind_method(D_METHOD("remove_script_support_override", "script"), &FontData::remove_script_support_override);
- ClassDB::bind_method(D_METHOD("get_script_support_overrides"), &FontData::get_script_support_overrides);
+ buffer->draw_outline(p_canvas_item, ofs, p_size, p_modulate);
+}
- ClassDB::bind_method(D_METHOD("set_opentype_feature_overrides", "overrides"), &FontData::set_opentype_feature_overrides);
- ClassDB::bind_method(D_METHOD("get_opentype_feature_overrides"), &FontData::get_opentype_feature_overrides);
+void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, uint16_t p_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
+ uint64_t hash = p_text.hash64();
+ hash = hash_djb2_one_64(p_font_size, hash);
+ hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
+ hash = hash_djb2_one_64(p_flags, hash);
+ hash = hash_djb2_one_64(p_direction, hash);
+ hash = hash_djb2_one_64(p_orientation, hash);
- ClassDB::bind_method(D_METHOD("has_char", "char"), &FontData::has_char);
- ClassDB::bind_method(D_METHOD("get_supported_chars"), &FontData::get_supported_chars);
+ Ref<TextParagraph> lines_buffer;
+ if (cache_wrap.has(hash)) {
+ lines_buffer = cache_wrap.get(hash);
+ } else {
+ lines_buffer.instantiate();
+ lines_buffer->set_direction(p_direction);
+ lines_buffer->set_orientation(p_orientation);
+ lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
+ lines_buffer->set_width(p_width);
+ lines_buffer->set_flags(p_flags);
+ cache_wrap.insert(hash, lines_buffer);
+ }
- ClassDB::bind_method(D_METHOD("get_glyph_index", "size", "char", "variation_selector"), &FontData::get_glyph_index);
+ Vector2 ofs = p_pos;
+ if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.y -= lines_buffer->get_line_ascent(0);
+ } else {
+ ofs.x -= lines_buffer->get_line_ascent(0);
+ }
- ClassDB::bind_method(D_METHOD("get_supported_feature_list"), &FontData::get_supported_feature_list);
- ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &FontData::get_supported_variation_list);
+ lines_buffer->set_alignment(p_alignment);
+ lines_buffer->set_max_lines_visible(p_max_lines);
- ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "face_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_face_index", "get_face_index");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_force_autohinter", "is_force_autohinter");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_STORAGE), "set_hinting", "get_hinting");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_oversampling", "get_oversampling");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_fixed_size", "get_fixed_size");
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_opentype_feature_overrides", "get_opentype_feature_overrides");
+ lines_buffer->draw_outline(p_canvas_item, ofs, p_size, p_modulate);
}
-bool FontData::_set(const StringName &p_name, const Variant &p_value) {
- Vector<String> tokens = p_name.operator String().split("/");
- if (tokens.size() == 2 && tokens[0] == "language_support_override") {
- String lang = tokens[1];
- set_language_support_override(lang, p_value);
- return true;
- } else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
- String script = tokens[1];
- set_script_support_override(script, p_value);
- return true;
- } else if (tokens.size() >= 3 && tokens[0] == "cache") {
- int cache_index = tokens[1].to_int();
- if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
- set_variation_coordinates(cache_index, p_value);
- return true;
- }
- if (tokens.size() >= 5) {
- Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
- if (tokens[4] == "ascent") {
- set_ascent(cache_index, sz.x, p_value);
- return true;
- } else if (tokens[4] == "descent") {
- set_descent(cache_index, sz.x, p_value);
- return true;
- } else if (tokens[4] == "underline_position") {
- set_underline_position(cache_index, sz.x, p_value);
- return true;
- } else if (tokens[4] == "underline_thickness") {
- set_underline_thickness(cache_index, sz.x, p_value);
- return true;
- } else if (tokens[4] == "scale") {
- set_scale(cache_index, sz.x, p_value);
- return true;
- } else if (tokens[4] == "spacing_glyph") {
- set_spacing(cache_index, sz.x, TextServer::SPACING_GLYPH, p_value);
- return true;
- } else if (tokens[4] == "spacing_space") {
- set_spacing(cache_index, sz.x, TextServer::SPACING_SPACE, p_value);
- return true;
- } else if (tokens.size() == 7 && tokens[4] == "textures") {
- int texture_index = tokens[5].to_int();
- if (tokens[6] == "image") {
- set_texture_image(cache_index, sz, texture_index, p_value);
- return true;
- } else if (tokens[6] == "offsets") {
- set_texture_offsets(cache_index, sz, texture_index, p_value);
- return true;
- }
- } else if (tokens.size() == 7 && tokens[4] == "glyphs") {
- int32_t glyph_index = tokens[5].to_int();
- if (tokens[6] == "advance") {
- set_glyph_advance(cache_index, sz.x, glyph_index, p_value);
- return true;
- } else if (tokens[6] == "offset") {
- set_glyph_offset(cache_index, sz, glyph_index, p_value);
- return true;
- } else if (tokens[6] == "size") {
- set_glyph_size(cache_index, sz, glyph_index, p_value);
- return true;
- } else if (tokens[6] == "uv_rect") {
- set_glyph_uv_rect(cache_index, sz, glyph_index, p_value);
- return true;
- } else if (tokens[6] == "texture_idx") {
- set_glyph_texture_idx(cache_index, sz, glyph_index, p_value);
- return true;
- }
- } else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
- Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
- set_kerning(cache_index, sz.x, gp, p_value);
- return true;
- }
+// Drawing char.
+Size2 Font::get_char_size(char32_t p_char, int p_font_size) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ for (int i = 0; i < rids.size(); i++) {
+ if (TS->font_has_char(rids[i], p_char)) {
+ int32_t glyph = TS->font_get_glyph_index(rids[i], p_font_size, p_char, 0);
+ return Size2(TS->font_get_glyph_advance(rids[i], p_font_size, glyph).x, get_height(p_font_size));
}
}
- return false;
+ return Size2();
}
-bool FontData::_get(const StringName &p_name, Variant &r_ret) const {
- Vector<String> tokens = p_name.operator String().split("/");
- if (tokens.size() == 2 && tokens[0] == "language_support_override") {
- String lang = tokens[1];
- r_ret = get_language_support_override(lang);
- return true;
- } else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
- String script = tokens[1];
- r_ret = get_script_support_override(script);
- return true;
- } else if (tokens.size() >= 3 && tokens[0] == "cache") {
- int cache_index = tokens[1].to_int();
- if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
- r_ret = get_variation_coordinates(cache_index);
- return true;
+real_t Font::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size, const Color &p_modulate) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ for (int i = 0; i < rids.size(); i++) {
+ if (TS->font_has_char(rids[i], p_char)) {
+ int32_t glyph = TS->font_get_glyph_index(rids[i], p_font_size, p_char, 0);
+ TS->font_draw_glyph(rids[i], p_canvas_item, p_font_size, p_pos, glyph, p_modulate);
+ return TS->font_get_glyph_advance(rids[i], p_font_size, glyph).x;
}
- if (tokens.size() >= 5) {
- Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
- if (tokens[4] == "ascent") {
- r_ret = get_ascent(cache_index, sz.x);
- return true;
- } else if (tokens[4] == "descent") {
- r_ret = get_descent(cache_index, sz.x);
- return true;
- } else if (tokens[4] == "underline_position") {
- r_ret = get_underline_position(cache_index, sz.x);
- return true;
- } else if (tokens[4] == "underline_thickness") {
- r_ret = get_underline_thickness(cache_index, sz.x);
- return true;
- } else if (tokens[4] == "scale") {
- r_ret = get_scale(cache_index, sz.x);
- return true;
- } else if (tokens[4] == "spacing_glyph") {
- r_ret = get_spacing(cache_index, sz.x, TextServer::SPACING_GLYPH);
- return true;
- } else if (tokens[4] == "spacing_space") {
- r_ret = get_spacing(cache_index, sz.x, TextServer::SPACING_SPACE);
- return true;
- } else if (tokens.size() == 7 && tokens[4] == "textures") {
- int texture_index = tokens[5].to_int();
- if (tokens[6] == "image") {
- r_ret = get_texture_image(cache_index, sz, texture_index);
- return true;
- } else if (tokens[6] == "offsets") {
- r_ret = get_texture_offsets(cache_index, sz, texture_index);
- return true;
- }
- } else if (tokens.size() == 7 && tokens[4] == "glyphs") {
- int32_t glyph_index = tokens[5].to_int();
- if (tokens[6] == "advance") {
- r_ret = get_glyph_advance(cache_index, sz.x, glyph_index);
- return true;
- } else if (tokens[6] == "offset") {
- r_ret = get_glyph_offset(cache_index, sz, glyph_index);
- return true;
- } else if (tokens[6] == "size") {
- r_ret = get_glyph_size(cache_index, sz, glyph_index);
- return true;
- } else if (tokens[6] == "uv_rect") {
- r_ret = get_glyph_uv_rect(cache_index, sz, glyph_index);
- return true;
- } else if (tokens[6] == "texture_idx") {
- r_ret = get_glyph_texture_idx(cache_index, sz, glyph_index);
- return true;
- }
- } else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
- Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
- r_ret = get_kerning(cache_index, sz.x, gp);
- return true;
- }
+ }
+ return 0.f;
+}
+
+real_t Font::draw_char_outline(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size, int p_size, const Color &p_modulate) const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ for (int i = 0; i < rids.size(); i++) {
+ if (TS->font_has_char(rids[i], p_char)) {
+ int32_t glyph = TS->font_get_glyph_index(rids[i], p_font_size, p_char, 0);
+ TS->font_draw_glyph_outline(rids[i], p_canvas_item, p_font_size, p_size, p_pos, glyph, p_modulate);
+ return TS->font_get_glyph_advance(rids[i], p_font_size, glyph).x;
}
}
- return false;
+ return 0.f;
}
-void FontData::_get_property_list(List<PropertyInfo> *p_list) const {
- Vector<String> lang_over = get_language_support_overrides();
- for (int i = 0; i < lang_over.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::BOOL, "language_support_override/" + lang_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+// Helper functions.
+bool Font::has_char(char32_t p_char) const {
+ if (dirty_rids) {
+ _update_rids();
}
- Vector<String> scr_over = get_script_support_overrides();
- for (int i = 0; i < scr_over.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::BOOL, "script_support_override/" + scr_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ for (int i = 0; i < rids.size(); i++) {
+ if (TS->font_has_char(rids[i], p_char)) {
+ return true;
+ }
}
- for (int i = 0; i < cache.size(); i++) {
- String prefix = "cache/" + itos(i) + "/";
- Array sizes = get_size_cache_list(i);
- p_list->push_back(PropertyInfo(Variant::DICTIONARY, prefix + "variation_coordinates", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- for (int j = 0; j < sizes.size(); j++) {
- Vector2i sz = sizes[j];
- String prefix_sz = prefix + itos(sz.x) + "/" + itos(sz.y) + "/";
- if (sz.y == 0) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "ascent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "descent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_thickness", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix_sz + "spacing_glyph", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::BOOL, prefix_sz + "spacing_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- }
+ return false;
+}
- int tx_cnt = get_texture_count(i, sz);
- for (int k = 0; k < tx_cnt; k++) {
- p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, prefix_sz + "textures/" + itos(k) + "/offsets", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::OBJECT, prefix_sz + "textures/" + itos(k) + "/image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT));
- }
- Array glyphs = get_glyph_list(i, sz);
- for (int k = 0; k < glyphs.size(); k++) {
- const int32_t &gl = glyphs[k];
- if (sz.y == 0) {
- p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/advance", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- }
- p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::RECT2, prefix_sz + "glyphs/" + itos(gl) + "/uv_rect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- p_list->push_back(PropertyInfo(Variant::INT, prefix_sz + "glyphs/" + itos(gl) + "/texture_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- }
- if (sz.y == 0) {
- Array kerning_map = get_kerning_list(i, sz.x);
- for (int k = 0; k < kerning_map.size(); k++) {
- const Vector2i &gl_pair = kerning_map[k];
- p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "kerning_overrides/" + itos(gl_pair.x) + "/" + itos(gl_pair.y), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
- }
+String Font::get_supported_chars() const {
+ if (dirty_rids) {
+ _update_rids();
+ }
+ String chars;
+ for (int i = 0; i < rids.size(); i++) {
+ String data_chars = TS->font_get_supported_chars(rids[i]);
+ for (int j = 0; j < data_chars.length(); j++) {
+ if (chars.find_char(data_chars[j]) == -1) {
+ chars += data_chars[j];
}
}
}
+ return chars;
}
-void FontData::reset_state() {
- _clear_cache();
- data.clear();
- data_ptr = nullptr;
- data_size = 0;
- face_index = 0;
- cache.clear();
+bool Font::is_language_supported(const String &p_language) const {
+ return TS->font_is_language_supported(_get_rid(), p_language);
+}
- antialiased = true;
- mipmaps = false;
- msdf = false;
- force_autohinter = false;
- hinting = TextServer::HINTING_LIGHT;
- subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
- msdf_pixel_range = 14;
- msdf_size = 128;
- fixed_size = 0;
- embolden = 0.f;
- transform = Transform2D();
- oversampling = 0.f;
+bool Font::is_script_supported(const String &p_script) const {
+ return TS->font_is_script_supported(_get_rid(), p_script);
+}
+
+Dictionary Font::get_supported_feature_list() const {
+ return TS->font_supported_feature_list(_get_rid());
+}
+
+Dictionary Font::get_supported_variation_list() const {
+ return TS->font_supported_variation_list(_get_rid());
+}
+
+int64_t Font::get_face_count() const {
+ return TS->font_get_face_count(_get_rid());
+}
+
+Font::Font() {
+ cache.set_capacity(64);
+ cache_wrap.set_capacity(16);
+}
+
+Font::~Font() {
+ reset_state();
}
-void FontData::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) {
+/*************************************************************************/
+/* FontFile */
+/*************************************************************************/
+
+_FORCE_INLINE_ void FontFile::_clear_cache() {
+ for (int i = 0; i < cache.size(); i++) {
+ if (cache[i].is_valid()) {
+ TS->free_rid(cache[i]);
+ cache.write[i] = RID();
+ }
+ }
+}
+
+_FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index) const {
+ if (unlikely(p_cache_index >= cache.size())) {
+ cache.resize(p_cache_index + 1);
+ }
+ if (unlikely(!cache[p_cache_index].is_valid())) {
+ cache.write[p_cache_index] = TS->create_font();
+ TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
+ TS->font_set_antialiased(cache[p_cache_index], antialiased);
+ TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
+ TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
+ TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range);
+ TS->font_set_msdf_size(cache[p_cache_index], msdf_size);
+ TS->font_set_fixed_size(cache[p_cache_index], fixed_size);
+ TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
+ TS->font_set_hinting(cache[p_cache_index], hinting);
+ TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
+ TS->font_set_oversampling(cache[p_cache_index], oversampling);
+ }
+}
+
+void FontFile::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) {
int w = p_source->get_width();
int h = p_source->get_height();
@@ -516,7 +617,7 @@ void FontData::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz)
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a);
}
-void FontData::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
+void FontFile::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
int w = p_source->get_width();
int h = p_source->get_height();
@@ -616,7 +717,7 @@ void FontData::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz)
set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 3, img_ao);
}
-void FontData::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
+void FontFile::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
int w = p_source->get_width();
int h = p_source->get_height();
@@ -672,7 +773,7 @@ void FontData::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
set_texture_image(0, Vector2i(p_sz, 1), p_page, img_o);
}
-void FontData::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
+void FontFile::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
int w = p_source->get_width();
int h = p_source->get_height();
@@ -701,7 +802,7 @@ void FontData::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, in
set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_g);
}
-void FontData::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
+void FontFile::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
int w = p_source->get_width();
int h = p_source->get_height();
@@ -744,9 +845,477 @@ void FontData::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, in
set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_o);
}
+void FontFile::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("load_bitmap_font", "path"), &FontFile::load_bitmap_font);
+ ClassDB::bind_method(D_METHOD("load_dynamic_font", "path"), &FontFile::load_dynamic_font);
+
+ ClassDB::bind_method(D_METHOD("set_data", "data"), &FontFile::set_data);
+ ClassDB::bind_method(D_METHOD("get_data"), &FontFile::get_data);
+
+ ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontFile::set_font_name);
+ ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name);
+ ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style);
+
+ ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontFile::set_antialiased);
+ ClassDB::bind_method(D_METHOD("is_antialiased"), &FontFile::is_antialiased);
+
+ ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps);
+
+ ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &FontFile::set_multichannel_signed_distance_field);
+ ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &FontFile::is_multichannel_signed_distance_field);
+
+ ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "msdf_pixel_range"), &FontFile::set_msdf_pixel_range);
+ ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &FontFile::get_msdf_pixel_range);
+
+ ClassDB::bind_method(D_METHOD("set_msdf_size", "msdf_size"), &FontFile::set_msdf_size);
+ ClassDB::bind_method(D_METHOD("get_msdf_size"), &FontFile::get_msdf_size);
+
+ ClassDB::bind_method(D_METHOD("set_fixed_size", "fixed_size"), &FontFile::set_fixed_size);
+ ClassDB::bind_method(D_METHOD("get_fixed_size"), &FontFile::get_fixed_size);
+
+ ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &FontFile::set_force_autohinter);
+ ClassDB::bind_method(D_METHOD("is_force_autohinter"), &FontFile::is_force_autohinter);
+
+ ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &FontFile::set_hinting);
+ ClassDB::bind_method(D_METHOD("get_hinting"), &FontFile::get_hinting);
+
+ ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontFile::set_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontFile::get_subpixel_positioning);
+
+ ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontFile::set_oversampling);
+ ClassDB::bind_method(D_METHOD("get_oversampling"), &FontFile::get_oversampling);
+
+ ClassDB::bind_method(D_METHOD("get_cache_count"), &FontFile::get_cache_count);
+ ClassDB::bind_method(D_METHOD("clear_cache"), &FontFile::clear_cache);
+ ClassDB::bind_method(D_METHOD("remove_cache", "cache_index"), &FontFile::remove_cache);
+
+ ClassDB::bind_method(D_METHOD("get_size_cache_list", "cache_index"), &FontFile::get_size_cache_list);
+ ClassDB::bind_method(D_METHOD("clear_size_cache", "cache_index"), &FontFile::clear_size_cache);
+ ClassDB::bind_method(D_METHOD("remove_size_cache", "cache_index", "size"), &FontFile::remove_size_cache);
+
+ ClassDB::bind_method(D_METHOD("set_variation_coordinates", "cache_index", "variation_coordinates"), &FontFile::set_variation_coordinates);
+ ClassDB::bind_method(D_METHOD("get_variation_coordinates", "cache_index"), &FontFile::get_variation_coordinates);
+
+ ClassDB::bind_method(D_METHOD("set_embolden", "cache_index", "strength"), &FontFile::set_embolden);
+ ClassDB::bind_method(D_METHOD("get_embolden", "cache_index"), &FontFile::get_embolden);
+
+ ClassDB::bind_method(D_METHOD("set_transform", "cache_index", "transform"), &FontFile::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform", "cache_index"), &FontFile::get_transform);
+
+ ClassDB::bind_method(D_METHOD("set_face_index", "cache_index", "face_index"), &FontFile::set_face_index);
+ ClassDB::bind_method(D_METHOD("get_face_index", "cache_index"), &FontFile::get_face_index);
+
+ ClassDB::bind_method(D_METHOD("set_cache_ascent", "cache_index", "size", "ascent"), &FontFile::set_cache_ascent);
+ ClassDB::bind_method(D_METHOD("get_cache_ascent", "cache_index", "size"), &FontFile::get_cache_ascent);
+
+ ClassDB::bind_method(D_METHOD("set_cache_descent", "cache_index", "size", "descent"), &FontFile::set_cache_descent);
+ ClassDB::bind_method(D_METHOD("get_cache_descent", "cache_index", "size"), &FontFile::get_cache_descent);
+
+ ClassDB::bind_method(D_METHOD("set_cache_underline_position", "cache_index", "size", "underline_position"), &FontFile::set_cache_underline_position);
+ ClassDB::bind_method(D_METHOD("get_cache_underline_position", "cache_index", "size"), &FontFile::get_cache_underline_position);
+
+ ClassDB::bind_method(D_METHOD("set_cache_underline_thickness", "cache_index", "size", "underline_thickness"), &FontFile::set_cache_underline_thickness);
+ ClassDB::bind_method(D_METHOD("get_cache_underline_thickness", "cache_index", "size"), &FontFile::get_cache_underline_thickness);
+
+ ClassDB::bind_method(D_METHOD("set_cache_scale", "cache_index", "size", "scale"), &FontFile::set_cache_scale);
+ ClassDB::bind_method(D_METHOD("get_cache_scale", "cache_index", "size"), &FontFile::get_cache_scale);
+
+ ClassDB::bind_method(D_METHOD("get_texture_count", "cache_index", "size"), &FontFile::get_texture_count);
+ ClassDB::bind_method(D_METHOD("clear_textures", "cache_index", "size"), &FontFile::clear_textures);
+ ClassDB::bind_method(D_METHOD("remove_texture", "cache_index", "size", "texture_index"), &FontFile::remove_texture);
+
+ ClassDB::bind_method(D_METHOD("set_texture_image", "cache_index", "size", "texture_index", "image"), &FontFile::set_texture_image);
+ ClassDB::bind_method(D_METHOD("get_texture_image", "cache_index", "size", "texture_index"), &FontFile::get_texture_image);
+
+ ClassDB::bind_method(D_METHOD("set_texture_offsets", "cache_index", "size", "texture_index", "offset"), &FontFile::set_texture_offsets);
+ ClassDB::bind_method(D_METHOD("get_texture_offsets", "cache_index", "size", "texture_index"), &FontFile::get_texture_offsets);
+
+ ClassDB::bind_method(D_METHOD("get_glyph_list", "cache_index", "size"), &FontFile::get_glyph_list);
+ ClassDB::bind_method(D_METHOD("clear_glyphs", "cache_index", "size"), &FontFile::clear_glyphs);
+ ClassDB::bind_method(D_METHOD("remove_glyph", "cache_index", "size", "glyph"), &FontFile::remove_glyph);
+
+ ClassDB::bind_method(D_METHOD("set_glyph_advance", "cache_index", "size", "glyph", "advance"), &FontFile::set_glyph_advance);
+ ClassDB::bind_method(D_METHOD("get_glyph_advance", "cache_index", "size", "glyph"), &FontFile::get_glyph_advance);
+
+ ClassDB::bind_method(D_METHOD("set_glyph_offset", "cache_index", "size", "glyph", "offset"), &FontFile::set_glyph_offset);
+ ClassDB::bind_method(D_METHOD("get_glyph_offset", "cache_index", "size", "glyph"), &FontFile::get_glyph_offset);
+
+ ClassDB::bind_method(D_METHOD("set_glyph_size", "cache_index", "size", "glyph", "gl_size"), &FontFile::set_glyph_size);
+ ClassDB::bind_method(D_METHOD("get_glyph_size", "cache_index", "size", "glyph"), &FontFile::get_glyph_size);
+
+ ClassDB::bind_method(D_METHOD("set_glyph_uv_rect", "cache_index", "size", "glyph", "uv_rect"), &FontFile::set_glyph_uv_rect);
+ ClassDB::bind_method(D_METHOD("get_glyph_uv_rect", "cache_index", "size", "glyph"), &FontFile::get_glyph_uv_rect);
+
+ ClassDB::bind_method(D_METHOD("set_glyph_texture_idx", "cache_index", "size", "glyph", "texture_idx"), &FontFile::set_glyph_texture_idx);
+ ClassDB::bind_method(D_METHOD("get_glyph_texture_idx", "cache_index", "size", "glyph"), &FontFile::get_glyph_texture_idx);
+
+ ClassDB::bind_method(D_METHOD("get_kerning_list", "cache_index", "size"), &FontFile::get_kerning_list);
+ ClassDB::bind_method(D_METHOD("clear_kerning_map", "cache_index", "size"), &FontFile::clear_kerning_map);
+ ClassDB::bind_method(D_METHOD("remove_kerning", "cache_index", "size", "glyph_pair"), &FontFile::remove_kerning);
+
+ ClassDB::bind_method(D_METHOD("set_kerning", "cache_index", "size", "glyph_pair", "kerning"), &FontFile::set_kerning);
+ ClassDB::bind_method(D_METHOD("get_kerning", "cache_index", "size", "glyph_pair"), &FontFile::get_kerning);
+
+ ClassDB::bind_method(D_METHOD("render_range", "cache_index", "size", "start", "end"), &FontFile::render_range);
+ ClassDB::bind_method(D_METHOD("render_glyph", "cache_index", "size", "index"), &FontFile::render_glyph);
+
+ ClassDB::bind_method(D_METHOD("set_language_support_override", "language", "supported"), &FontFile::set_language_support_override);
+ ClassDB::bind_method(D_METHOD("get_language_support_override", "language"), &FontFile::get_language_support_override);
+ ClassDB::bind_method(D_METHOD("remove_language_support_override", "language"), &FontFile::remove_language_support_override);
+ ClassDB::bind_method(D_METHOD("get_language_support_overrides"), &FontFile::get_language_support_overrides);
+
+ ClassDB::bind_method(D_METHOD("set_script_support_override", "script", "supported"), &FontFile::set_script_support_override);
+ ClassDB::bind_method(D_METHOD("get_script_support_override", "script"), &FontFile::get_script_support_override);
+ ClassDB::bind_method(D_METHOD("remove_script_support_override", "script"), &FontFile::remove_script_support_override);
+ ClassDB::bind_method(D_METHOD("get_script_support_overrides"), &FontFile::get_script_support_overrides);
+
+ ClassDB::bind_method(D_METHOD("set_opentype_feature_overrides", "overrides"), &FontFile::set_opentype_feature_overrides);
+ ClassDB::bind_method(D_METHOD("get_opentype_feature_overrides"), &FontFile::get_opentype_feature_overrides);
+
+ ClassDB::bind_method(D_METHOD("get_glyph_index", "size", "char", "variation_selector"), &FontFile::get_glyph_index);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_force_autohinter", "is_force_autohinter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_STORAGE), "set_hinting", "get_hinting");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_oversampling", "get_oversampling");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_fixed_size", "get_fixed_size");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_opentype_feature_overrides", "get_opentype_feature_overrides");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font"), PROPERTY_USAGE_STORAGE), "set_fallbacks", "get_fallbacks");
+}
+
+bool FontFile::_set(const StringName &p_name, const Variant &p_value) {
+ Vector<String> tokens = p_name.operator String().split("/");
+
+#ifndef DISABLE_DEPRECATED
+ if (tokens.size() == 1 && tokens[0] == "font_path") {
+ // Compatibility, DynamicFontData.
+ load_dynamic_font(p_value);
+ } else if (tokens.size() == 1 && tokens[0] == "override_oversampling") {
+ set_oversampling(p_value);
+ }
+ if (tokens.size() == 1 && tokens[0] == "font_data") {
+ // Compatibility, DynamicFont.
+ Ref<Font> f = p_value;
+ if (f.is_valid()) {
+ fallbacks.push_back(f);
+ return true;
+ }
+ return false;
+ } else if (tokens.size() == 2 && tokens[0] == "fallback") {
+ // Compatibility, DynamicFont.
+ Ref<FontFile> f = p_value;
+ if (f.is_valid()) {
+ fallbacks.push_back(f);
+ return true;
+ }
+ return false;
+ } else if (tokens.size() == 1 && tokens[0] == "textures") {
+ // Compatibility, BitmapFont.
+ set_fixed_size(16);
+ Array textures = p_value;
+ for (int i = 0; i < textures.size(); i++) {
+ Ref<ImageTexture> tex = textures[i];
+ ERR_CONTINUE(!tex.is_valid());
+ set_texture_image(0, Vector2i(16, 0), i, tex->get_image());
+ }
+ } else if (tokens.size() == 1 && tokens[0] == "chars") {
+ // Compatibility, BitmapFont.
+ set_fixed_size(16);
+ PackedInt32Array arr = p_value;
+ int len = arr.size();
+ ERR_FAIL_COND_V(len % 9, false);
+ if (!len) {
+ return false;
+ }
+ int chars = len / 9;
+ for (int i = 0; i < chars; i++) {
+ const int32_t *data = &arr[i * 9];
+ char32_t c = data[0];
+ set_glyph_texture_idx(0, Vector2i(16, 0), c, data[1]);
+ set_glyph_uv_rect(0, Vector2i(16, 0), c, Rect2(data[2], data[3], data[4], data[5]));
+ set_glyph_offset(0, Vector2i(16, 0), c, Size2(data[6], data[7]));
+ set_glyph_advance(0, 16, c, Vector2(data[8], 0));
+ }
+ } else if (tokens.size() == 1 && tokens[0] == "kernings") {
+ // Compatibility, BitmapFont.
+ set_fixed_size(16);
+ PackedInt32Array arr = p_value;
+ int len = arr.size();
+ ERR_FAIL_COND_V(len % 3, false);
+ if (!len) {
+ return false;
+ }
+ for (int i = 0; i < len / 3; i++) {
+ const int32_t *data = &arr[i * 3];
+ set_kerning(0, 16, Vector2i(data[0], data[1]), Vector2(data[2], 0));
+ }
+ } else if (tokens.size() == 1 && tokens[0] == "height") {
+ // Compatibility, BitmapFont.
+ bmp_height = p_value;
+ set_fixed_size(16);
+ set_cache_descent(0, 16, bmp_height - bmp_ascent);
+ } else if (tokens.size() == 1 && tokens[0] == "ascent") {
+ // Compatibility, BitmapFont.
+ bmp_ascent = p_value;
+ set_fixed_size(16);
+ set_cache_ascent(0, 16, bmp_ascent);
+ set_cache_descent(0, 16, bmp_height - bmp_ascent);
+ } else if (tokens.size() == 1 && tokens[0] == "fallback") {
+ // Compatibility, BitmapFont.
+ Ref<Font> f = p_value;
+ if (f.is_valid()) {
+ fallbacks.push_back(f);
+ return true;
+ }
+ return false;
+ }
+#endif // DISABLE_DEPRECATED
+
+ if (tokens.size() == 2 && tokens[0] == "language_support_override") {
+ String lang = tokens[1];
+ set_language_support_override(lang, p_value);
+ return true;
+ } else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
+ String script = tokens[1];
+ set_script_support_override(script, p_value);
+ return true;
+ } else if (tokens.size() >= 3 && tokens[0] == "cache") {
+ int cache_index = tokens[1].to_int();
+ if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
+ set_variation_coordinates(cache_index, p_value);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "embolden") {
+ set_embolden(cache_index, p_value);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "face_index") {
+ set_face_index(cache_index, p_value);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "transform") {
+ set_transform(cache_index, p_value);
+ return true;
+ }
+ if (tokens.size() >= 5) {
+ Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
+ if (tokens[4] == "ascent") {
+ set_cache_ascent(cache_index, sz.x, p_value);
+ return true;
+ } else if (tokens[4] == "descent") {
+ set_cache_descent(cache_index, sz.x, p_value);
+ return true;
+ } else if (tokens[4] == "underline_position") {
+ set_cache_underline_position(cache_index, sz.x, p_value);
+ return true;
+ } else if (tokens[4] == "underline_thickness") {
+ set_cache_underline_thickness(cache_index, sz.x, p_value);
+ return true;
+ } else if (tokens[4] == "scale") {
+ set_cache_scale(cache_index, sz.x, p_value);
+ return true;
+ } else if (tokens.size() == 7 && tokens[4] == "textures") {
+ int texture_index = tokens[5].to_int();
+ if (tokens[6] == "image") {
+ set_texture_image(cache_index, sz, texture_index, p_value);
+ return true;
+ } else if (tokens[6] == "offsets") {
+ set_texture_offsets(cache_index, sz, texture_index, p_value);
+ return true;
+ }
+ } else if (tokens.size() == 7 && tokens[4] == "glyphs") {
+ int32_t glyph_index = tokens[5].to_int();
+ if (tokens[6] == "advance") {
+ set_glyph_advance(cache_index, sz.x, glyph_index, p_value);
+ return true;
+ } else if (tokens[6] == "offset") {
+ set_glyph_offset(cache_index, sz, glyph_index, p_value);
+ return true;
+ } else if (tokens[6] == "size") {
+ set_glyph_size(cache_index, sz, glyph_index, p_value);
+ return true;
+ } else if (tokens[6] == "uv_rect") {
+ set_glyph_uv_rect(cache_index, sz, glyph_index, p_value);
+ return true;
+ } else if (tokens[6] == "texture_idx") {
+ set_glyph_texture_idx(cache_index, sz, glyph_index, p_value);
+ return true;
+ }
+ } else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
+ Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
+ set_kerning(cache_index, sz.x, gp, p_value);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool FontFile::_get(const StringName &p_name, Variant &r_ret) const {
+ Vector<String> tokens = p_name.operator String().split("/");
+ if (tokens.size() == 2 && tokens[0] == "language_support_override") {
+ String lang = tokens[1];
+ r_ret = get_language_support_override(lang);
+ return true;
+ } else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
+ String script = tokens[1];
+ r_ret = get_script_support_override(script);
+ return true;
+ } else if (tokens.size() >= 3 && tokens[0] == "cache") {
+ int cache_index = tokens[1].to_int();
+ if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
+ r_ret = get_variation_coordinates(cache_index);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "embolden") {
+ r_ret = get_embolden(cache_index);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "face_index") {
+ r_ret = get_face_index(cache_index);
+ return true;
+ } else if (tokens.size() == 3 && tokens[2] == "transform") {
+ r_ret = get_transform(cache_index);
+ return true;
+ }
+ if (tokens.size() >= 5) {
+ Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
+ if (tokens[4] == "ascent") {
+ r_ret = get_cache_ascent(cache_index, sz.x);
+ return true;
+ } else if (tokens[4] == "descent") {
+ r_ret = get_cache_descent(cache_index, sz.x);
+ return true;
+ } else if (tokens[4] == "underline_position") {
+ r_ret = get_cache_underline_position(cache_index, sz.x);
+ return true;
+ } else if (tokens[4] == "underline_thickness") {
+ r_ret = get_cache_underline_thickness(cache_index, sz.x);
+ return true;
+ } else if (tokens[4] == "scale") {
+ r_ret = get_cache_scale(cache_index, sz.x);
+ return true;
+ } else if (tokens.size() == 7 && tokens[4] == "textures") {
+ int texture_index = tokens[5].to_int();
+ if (tokens[6] == "image") {
+ r_ret = get_texture_image(cache_index, sz, texture_index);
+ return true;
+ } else if (tokens[6] == "offsets") {
+ r_ret = get_texture_offsets(cache_index, sz, texture_index);
+ return true;
+ }
+ } else if (tokens.size() == 7 && tokens[4] == "glyphs") {
+ int32_t glyph_index = tokens[5].to_int();
+ if (tokens[6] == "advance") {
+ r_ret = get_glyph_advance(cache_index, sz.x, glyph_index);
+ return true;
+ } else if (tokens[6] == "offset") {
+ r_ret = get_glyph_offset(cache_index, sz, glyph_index);
+ return true;
+ } else if (tokens[6] == "size") {
+ r_ret = get_glyph_size(cache_index, sz, glyph_index);
+ return true;
+ } else if (tokens[6] == "uv_rect") {
+ r_ret = get_glyph_uv_rect(cache_index, sz, glyph_index);
+ return true;
+ } else if (tokens[6] == "texture_idx") {
+ r_ret = get_glyph_texture_idx(cache_index, sz, glyph_index);
+ return true;
+ }
+ } else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
+ Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
+ r_ret = get_kerning(cache_index, sz.x, gp);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void FontFile::_get_property_list(List<PropertyInfo> *p_list) const {
+ Vector<String> lang_over = get_language_support_overrides();
+ for (int i = 0; i < lang_over.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "language_support_override/" + lang_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+ Vector<String> scr_over = get_script_support_overrides();
+ for (int i = 0; i < scr_over.size(); i++) {
+ p_list->push_back(PropertyInfo(Variant::BOOL, "script_support_override/" + scr_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+ for (int i = 0; i < cache.size(); i++) {
+ String prefix = "cache/" + itos(i) + "/";
+ Array sizes = get_size_cache_list(i);
+ p_list->push_back(PropertyInfo(Variant::DICTIONARY, prefix + "variation_coordinates", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::INT, "face_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+
+ for (int j = 0; j < sizes.size(); j++) {
+ Vector2i sz = sizes[j];
+ String prefix_sz = prefix + itos(sz.x) + "/" + itos(sz.y) + "/";
+ if (sz.y == 0) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "ascent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "descent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_thickness", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+
+ int tx_cnt = get_texture_count(i, sz);
+ for (int k = 0; k < tx_cnt; k++) {
+ p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, prefix_sz + "textures/" + itos(k) + "/offsets", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, prefix_sz + "textures/" + itos(k) + "/image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT));
+ }
+ Array glyphs = get_glyph_list(i, sz);
+ for (int k = 0; k < glyphs.size(); k++) {
+ const int32_t &gl = glyphs[k];
+ if (sz.y == 0) {
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/advance", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::RECT2, prefix_sz + "glyphs/" + itos(gl) + "/uv_rect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ p_list->push_back(PropertyInfo(Variant::INT, prefix_sz + "glyphs/" + itos(gl) + "/texture_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+ if (sz.y == 0) {
+ Array kerning_map = get_kerning_list(i, sz.x);
+ for (int k = 0; k < kerning_map.size(); k++) {
+ const Vector2i &gl_pair = kerning_map[k];
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "kerning_overrides/" + itos(gl_pair.x) + "/" + itos(gl_pair.y), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
+ }
+ }
+ }
+ }
+}
+
+void FontFile::reset_state() {
+ _clear_cache();
+ data.clear();
+ data_ptr = nullptr;
+ data_size = 0;
+ cache.clear();
+
+ antialiased = true;
+ mipmaps = false;
+ msdf = false;
+ force_autohinter = false;
+ hinting = TextServer::HINTING_LIGHT;
+ subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
+ msdf_pixel_range = 14;
+ msdf_size = 128;
+ fixed_size = 0;
+ oversampling = 0.f;
+
+ Font::reset_state();
+}
+
/*************************************************************************/
-Error FontData::load_bitmap_font(const String &p_path) {
+Error FontFile::load_bitmap_font(const String &p_path) {
reset_state();
antialiased = false;
@@ -1209,13 +1778,13 @@ Error FontData::load_bitmap_font(const String &p_path) {
set_font_name(font_name);
set_font_style(st_flags);
- set_ascent(0, base_size, ascent);
- set_descent(0, base_size, height - ascent);
+ set_cache_ascent(0, base_size, ascent);
+ set_cache_descent(0, base_size, height - ascent);
return OK;
}
-Error FontData::load_dynamic_font(const String &p_path) {
+Error FontFile::load_dynamic_font(const String &p_path) {
reset_state();
Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
@@ -1224,7 +1793,7 @@ Error FontData::load_dynamic_font(const String &p_path) {
return OK;
}
-void FontData::set_data_ptr(const uint8_t *p_data, size_t p_size) {
+void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) {
data.clear();
data_ptr = p_data;
data_size = p_size;
@@ -1238,7 +1807,7 @@ void FontData::set_data_ptr(const uint8_t *p_data, size_t p_size) {
}
}
-void FontData::set_data(const PackedByteArray &p_data) {
+void FontFile::set_data(const PackedByteArray &p_data) {
data = p_data;
data_ptr = data.ptr();
data_size = data.size();
@@ -1252,32 +1821,7 @@ void FontData::set_data(const PackedByteArray &p_data) {
}
}
-void FontData::set_face_index(int64_t p_index) {
- ERR_FAIL_COND(p_index < 0);
- ERR_FAIL_COND(p_index >= 0x7FFF);
-
- if (face_index != p_index) {
- face_index = p_index;
- if (data_ptr != nullptr) {
- for (int i = 0; i < cache.size(); i++) {
- if (cache[i].is_valid()) {
- TS->font_set_face_index(cache[i], face_index);
- }
- }
- }
- }
-}
-
-int64_t FontData::get_face_index() const {
- return face_index;
-}
-
-int64_t FontData::get_face_count() const {
- _ensure_rid(0);
- return TS->font_get_face_count(cache[0]);
-}
-
-PackedByteArray FontData::get_data() const {
+PackedByteArray FontFile::get_data() const {
if (unlikely((size_t)data.size() != data_size)) {
PackedByteArray *data_w = const_cast<PackedByteArray *>(&data);
data_w->resize(data_size);
@@ -1286,37 +1830,22 @@ PackedByteArray FontData::get_data() const {
return data;
}
-void FontData::set_font_name(const String &p_name) {
+void FontFile::set_font_name(const String &p_name) {
_ensure_rid(0);
TS->font_set_name(cache[0], p_name);
}
-String FontData::get_font_name() const {
- _ensure_rid(0);
- return TS->font_get_name(cache[0]);
-}
-
-void FontData::set_font_style_name(const String &p_name) {
+void FontFile::set_font_style_name(const String &p_name) {
_ensure_rid(0);
TS->font_set_style_name(cache[0], p_name);
}
-String FontData::get_font_style_name() const {
- _ensure_rid(0);
- return TS->font_get_style_name(cache[0]);
-}
-
-void FontData::set_font_style(uint32_t p_style) {
+void FontFile::set_font_style(uint32_t p_style) {
_ensure_rid(0);
TS->font_set_style(cache[0], p_style);
}
-uint32_t FontData::get_font_style() const {
- _ensure_rid(0);
- return TS->font_get_style(cache[0]);
-}
-
-void FontData::set_antialiased(bool p_antialiased) {
+void FontFile::set_antialiased(bool p_antialiased) {
if (antialiased != p_antialiased) {
antialiased = p_antialiased;
for (int i = 0; i < cache.size(); i++) {
@@ -1327,11 +1856,11 @@ void FontData::set_antialiased(bool p_antialiased) {
}
}
-bool FontData::is_antialiased() const {
+bool FontFile::is_antialiased() const {
return antialiased;
}
-void FontData::set_generate_mipmaps(bool p_generate_mipmaps) {
+void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) {
if (mipmaps != p_generate_mipmaps) {
mipmaps = p_generate_mipmaps;
for (int i = 0; i < cache.size(); i++) {
@@ -1342,11 +1871,11 @@ void FontData::set_generate_mipmaps(bool p_generate_mipmaps) {
}
}
-bool FontData::get_generate_mipmaps() const {
+bool FontFile::get_generate_mipmaps() const {
return mipmaps;
}
-void FontData::set_multichannel_signed_distance_field(bool p_msdf) {
+void FontFile::set_multichannel_signed_distance_field(bool p_msdf) {
if (msdf != p_msdf) {
msdf = p_msdf;
for (int i = 0; i < cache.size(); i++) {
@@ -1357,11 +1886,11 @@ void FontData::set_multichannel_signed_distance_field(bool p_msdf) {
}
}
-bool FontData::is_multichannel_signed_distance_field() const {
+bool FontFile::is_multichannel_signed_distance_field() const {
return msdf;
}
-void FontData::set_msdf_pixel_range(int p_msdf_pixel_range) {
+void FontFile::set_msdf_pixel_range(int p_msdf_pixel_range) {
if (msdf_pixel_range != p_msdf_pixel_range) {
msdf_pixel_range = p_msdf_pixel_range;
for (int i = 0; i < cache.size(); i++) {
@@ -1372,11 +1901,11 @@ void FontData::set_msdf_pixel_range(int p_msdf_pixel_range) {
}
}
-int FontData::get_msdf_pixel_range() const {
+int FontFile::get_msdf_pixel_range() const {
return msdf_pixel_range;
}
-void FontData::set_msdf_size(int p_msdf_size) {
+void FontFile::set_msdf_size(int p_msdf_size) {
if (msdf_size != p_msdf_size) {
msdf_size = p_msdf_size;
for (int i = 0; i < cache.size(); i++) {
@@ -1387,11 +1916,11 @@ void FontData::set_msdf_size(int p_msdf_size) {
}
}
-int FontData::get_msdf_size() const {
+int FontFile::get_msdf_size() const {
return msdf_size;
}
-void FontData::set_fixed_size(int p_fixed_size) {
+void FontFile::set_fixed_size(int p_fixed_size) {
if (fixed_size != p_fixed_size) {
fixed_size = p_fixed_size;
for (int i = 0; i < cache.size(); i++) {
@@ -1402,11 +1931,11 @@ void FontData::set_fixed_size(int p_fixed_size) {
}
}
-int FontData::get_fixed_size() const {
+int FontFile::get_fixed_size() const {
return fixed_size;
}
-void FontData::set_force_autohinter(bool p_force_autohinter) {
+void FontFile::set_force_autohinter(bool p_force_autohinter) {
if (force_autohinter != p_force_autohinter) {
force_autohinter = p_force_autohinter;
for (int i = 0; i < cache.size(); i++) {
@@ -1417,11 +1946,11 @@ void FontData::set_force_autohinter(bool p_force_autohinter) {
}
}
-bool FontData::is_force_autohinter() const {
+bool FontFile::is_force_autohinter() const {
return force_autohinter;
}
-void FontData::set_hinting(TextServer::Hinting p_hinting) {
+void FontFile::set_hinting(TextServer::Hinting p_hinting) {
if (hinting != p_hinting) {
hinting = p_hinting;
for (int i = 0; i < cache.size(); i++) {
@@ -1432,11 +1961,11 @@ void FontData::set_hinting(TextServer::Hinting p_hinting) {
}
}
-TextServer::Hinting FontData::get_hinting() const {
+TextServer::Hinting FontFile::get_hinting() const {
return hinting;
}
-void FontData::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
+void FontFile::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
if (subpixel_positioning != p_subpixel) {
subpixel_positioning = p_subpixel;
for (int i = 0; i < cache.size(); i++) {
@@ -1447,41 +1976,11 @@ void FontData::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpix
}
}
-TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
+TextServer::SubpixelPositioning FontFile::get_subpixel_positioning() const {
return subpixel_positioning;
}
-void FontData::set_embolden(float p_strength) {
- if (embolden != p_strength) {
- embolden = p_strength;
- for (int i = 0; i < cache.size(); i++) {
- _ensure_rid(i);
- TS->font_set_embolden(cache[i], embolden);
- }
- emit_changed();
- }
-}
-
-float FontData::get_embolden() const {
- return embolden;
-}
-
-void FontData::set_transform(Transform2D p_transform) {
- if (transform != p_transform) {
- transform = p_transform;
- for (int i = 0; i < cache.size(); i++) {
- _ensure_rid(i);
- TS->font_set_transform(cache[i], transform);
- }
- emit_changed();
- }
-}
-
-Transform2D FontData::get_transform() const {
- return transform;
-}
-
-void FontData::set_oversampling(real_t p_oversampling) {
+void FontFile::set_oversampling(real_t p_oversampling) {
if (oversampling != p_oversampling) {
oversampling = p_oversampling;
for (int i = 0; i < cache.size(); i++) {
@@ -1492,17 +1991,20 @@ void FontData::set_oversampling(real_t p_oversampling) {
}
}
-real_t FontData::get_oversampling() const {
+real_t FontFile::get_oversampling() const {
return oversampling;
}
-RID FontData::find_cache(const Dictionary &p_variation_coordinates) const {
+RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform) const {
// Find existing variation cache.
const Dictionary &supported_coords = get_supported_variation_list();
for (int i = 0; i < cache.size(); i++) {
if (cache[i].is_valid()) {
const Dictionary &cache_var = TS->font_get_variation_coordinates(cache[i]);
bool match = true;
+ match = match && (TS->font_get_face_index(cache[i]) == p_face_index);
+ match = match && (TS->font_get_embolden(cache[i]) == p_strength);
+ match = match && (TS->font_get_transform(cache[i]) == p_transform);
for (const Variant *V = supported_coords.next(nullptr); V && match; V = supported_coords.next(V)) {
const Vector3 &def = supported_coords[*V];
@@ -1538,19 +2040,28 @@ RID FontData::find_cache(const Dictionary &p_variation_coordinates) const {
int idx = cache.size();
_ensure_rid(idx);
TS->font_set_variation_coordinates(cache[idx], p_variation_coordinates);
+ TS->font_set_face_index(cache[idx], p_face_index);
+ TS->font_set_embolden(cache[idx], p_strength);
+ TS->font_set_transform(cache[idx], p_transform);
return cache[idx];
}
-int FontData::get_cache_count() const {
+RID FontFile::_get_rid() const {
+ _ensure_rid(0);
+ return cache[0];
+}
+
+int FontFile::get_cache_count() const {
return cache.size();
}
-void FontData::clear_cache() {
+void FontFile::clear_cache() {
_clear_cache();
cache.clear();
+ emit_changed();
}
-void FontData::remove_cache(int p_cache_index) {
+void FontFile::remove_cache(int p_cache_index) {
ERR_FAIL_INDEX(p_cache_index, cache.size());
if (cache[p_cache_index].is_valid()) {
TS->free_rid(cache.write[p_cache_index]);
@@ -1559,952 +2070,607 @@ void FontData::remove_cache(int p_cache_index) {
emit_changed();
}
-Array FontData::get_size_cache_list(int p_cache_index) const {
+Array FontFile::get_size_cache_list(int p_cache_index) const {
ERR_FAIL_COND_V(p_cache_index < 0, Array());
_ensure_rid(p_cache_index);
return TS->font_get_size_cache_list(cache[p_cache_index]);
}
-void FontData::clear_size_cache(int p_cache_index) {
+void FontFile::clear_size_cache(int p_cache_index) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_clear_size_cache(cache[p_cache_index]);
}
-void FontData::remove_size_cache(int p_cache_index, const Vector2i &p_size) {
+void FontFile::remove_size_cache(int p_cache_index, const Vector2i &p_size) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_remove_size_cache(cache[p_cache_index], p_size);
}
-void FontData::set_variation_coordinates(int p_cache_index, const Dictionary &p_variation_coordinates) {
+void FontFile::set_variation_coordinates(int p_cache_index, const Dictionary &p_variation_coordinates) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_variation_coordinates(cache[p_cache_index], p_variation_coordinates);
- emit_changed();
}
-Dictionary FontData::get_variation_coordinates(int p_cache_index) const {
+Dictionary FontFile::get_variation_coordinates(int p_cache_index) const {
ERR_FAIL_COND_V(p_cache_index < 0, Dictionary());
_ensure_rid(p_cache_index);
return TS->font_get_variation_coordinates(cache[p_cache_index]);
}
-void FontData::set_ascent(int p_cache_index, int p_size, real_t p_ascent) {
+void FontFile::set_embolden(int p_cache_index, float p_strength) {
+ ERR_FAIL_COND(p_cache_index < 0);
+ _ensure_rid(p_cache_index);
+ TS->font_set_embolden(cache[p_cache_index], p_strength);
+}
+
+float FontFile::get_embolden(int p_cache_index) const {
+ ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
+ _ensure_rid(p_cache_index);
+ return TS->font_get_embolden(cache[p_cache_index]);
+}
+
+void FontFile::set_transform(int p_cache_index, Transform2D p_transform) {
+ ERR_FAIL_COND(p_cache_index < 0);
+ _ensure_rid(p_cache_index);
+ TS->font_set_transform(cache[p_cache_index], p_transform);
+}
+
+Transform2D FontFile::get_transform(int p_cache_index) const {
+ ERR_FAIL_COND_V(p_cache_index < 0, Transform2D());
+ _ensure_rid(p_cache_index);
+ return TS->font_get_transform(cache[p_cache_index]);
+}
+
+void FontFile::set_face_index(int p_cache_index, int64_t p_index) {
+ ERR_FAIL_COND(p_cache_index < 0);
+ ERR_FAIL_COND(p_index < 0);
+ ERR_FAIL_COND(p_index >= 0x7FFF);
+
+ _ensure_rid(p_cache_index);
+ TS->font_set_face_index(cache[p_cache_index], p_index);
+}
+
+int64_t FontFile::get_face_index(int p_cache_index) const {
+ ERR_FAIL_COND_V(p_cache_index < 0, 0);
+ _ensure_rid(p_cache_index);
+ return TS->font_get_face_index(cache[p_cache_index]);
+}
+
+void FontFile::set_cache_ascent(int p_cache_index, int p_size, real_t p_ascent) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_ascent(cache[p_cache_index], p_size, p_ascent);
}
-real_t FontData::get_ascent(int p_cache_index, int p_size) const {
+real_t FontFile::get_cache_ascent(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
_ensure_rid(p_cache_index);
return TS->font_get_ascent(cache[p_cache_index], p_size);
}
-void FontData::set_descent(int p_cache_index, int p_size, real_t p_descent) {
+void FontFile::set_cache_descent(int p_cache_index, int p_size, real_t p_descent) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_descent(cache[p_cache_index], p_size, p_descent);
}
-real_t FontData::get_descent(int p_cache_index, int p_size) const {
+real_t FontFile::get_cache_descent(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
_ensure_rid(p_cache_index);
return TS->font_get_descent(cache[p_cache_index], p_size);
}
-void FontData::set_underline_position(int p_cache_index, int p_size, real_t p_underline_position) {
+void FontFile::set_cache_underline_position(int p_cache_index, int p_size, real_t p_underline_position) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_underline_position(cache[p_cache_index], p_size, p_underline_position);
}
-real_t FontData::get_underline_position(int p_cache_index, int p_size) const {
+real_t FontFile::get_cache_underline_position(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
_ensure_rid(p_cache_index);
return TS->font_get_underline_position(cache[p_cache_index], p_size);
}
-void FontData::set_underline_thickness(int p_cache_index, int p_size, real_t p_underline_thickness) {
+void FontFile::set_cache_underline_thickness(int p_cache_index, int p_size, real_t p_underline_thickness) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_underline_thickness(cache[p_cache_index], p_size, p_underline_thickness);
}
-real_t FontData::get_underline_thickness(int p_cache_index, int p_size) const {
+real_t FontFile::get_cache_underline_thickness(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
_ensure_rid(p_cache_index);
return TS->font_get_underline_thickness(cache[p_cache_index], p_size);
}
-void FontData::set_scale(int p_cache_index, int p_size, real_t p_scale) {
+void FontFile::set_cache_scale(int p_cache_index, int p_size, real_t p_scale) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_scale(cache[p_cache_index], p_size, p_scale);
}
-real_t FontData::get_scale(int p_cache_index, int p_size) const {
+real_t FontFile::get_cache_scale(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
_ensure_rid(p_cache_index);
return TS->font_get_scale(cache[p_cache_index], p_size);
}
-void FontData::set_spacing(int p_cache_index, int p_size, TextServer::SpacingType p_spacing, int p_value) {
- ERR_FAIL_COND(p_cache_index < 0);
- _ensure_rid(p_cache_index);
- TS->font_set_spacing(cache[p_cache_index], p_size, p_spacing, p_value);
-}
-
-int FontData::get_spacing(int p_cache_index, int p_size, TextServer::SpacingType p_spacing) const {
- ERR_FAIL_COND_V(p_cache_index < 0, 0);
- _ensure_rid(p_cache_index);
- return TS->font_get_spacing(cache[p_cache_index], p_size, p_spacing);
-}
-
-int FontData::get_texture_count(int p_cache_index, const Vector2i &p_size) const {
+int FontFile::get_texture_count(int p_cache_index, const Vector2i &p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0);
_ensure_rid(p_cache_index);
return TS->font_get_texture_count(cache[p_cache_index], p_size);
}
-void FontData::clear_textures(int p_cache_index, const Vector2i &p_size) {
+void FontFile::clear_textures(int p_cache_index, const Vector2i &p_size) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_clear_textures(cache[p_cache_index], p_size);
}
-void FontData::remove_texture(int p_cache_index, const Vector2i &p_size, int p_texture_index) {
+void FontFile::remove_texture(int p_cache_index, const Vector2i &p_size, int p_texture_index) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_remove_texture(cache[p_cache_index], p_size, p_texture_index);
}
-void FontData::set_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
+void FontFile::set_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_texture_image(cache[p_cache_index], p_size, p_texture_index, p_image);
}
-Ref<Image> FontData::get_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
+Ref<Image> FontFile::get_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
ERR_FAIL_COND_V(p_cache_index < 0, Ref<Image>());
_ensure_rid(p_cache_index);
return TS->font_get_texture_image(cache[p_cache_index], p_size, p_texture_index);
}
-void FontData::set_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
+void FontFile::set_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_texture_offsets(cache[p_cache_index], p_size, p_texture_index, p_offset);
}
-PackedInt32Array FontData::get_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
+PackedInt32Array FontFile::get_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
ERR_FAIL_COND_V(p_cache_index < 0, PackedInt32Array());
_ensure_rid(p_cache_index);
return TS->font_get_texture_offsets(cache[p_cache_index], p_size, p_texture_index);
}
-Array FontData::get_glyph_list(int p_cache_index, const Vector2i &p_size) const {
+Array FontFile::get_glyph_list(int p_cache_index, const Vector2i &p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, Array());
_ensure_rid(p_cache_index);
return TS->font_get_glyph_list(cache[p_cache_index], p_size);
}
-void FontData::clear_glyphs(int p_cache_index, const Vector2i &p_size) {
+void FontFile::clear_glyphs(int p_cache_index, const Vector2i &p_size) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_clear_glyphs(cache[p_cache_index], p_size);
}
-void FontData::remove_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) {
+void FontFile::remove_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_remove_glyph(cache[p_cache_index], p_size, p_glyph);
}
-void FontData::set_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
+void FontFile::set_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_glyph_advance(cache[p_cache_index], p_size, p_glyph, p_advance);
}
-Vector2 FontData::get_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph) const {
+Vector2 FontFile::get_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
_ensure_rid(p_cache_index);
return TS->font_get_glyph_advance(cache[p_cache_index], p_size, p_glyph);
}
-void FontData::set_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
+void FontFile::set_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_glyph_offset(cache[p_cache_index], p_size, p_glyph, p_offset);
}
-Vector2 FontData::get_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
+Vector2 FontFile::get_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
_ensure_rid(p_cache_index);
return TS->font_get_glyph_offset(cache[p_cache_index], p_size, p_glyph);
}
-void FontData::set_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
+void FontFile::set_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_glyph_size(cache[p_cache_index], p_size, p_glyph, p_gl_size);
}
-Vector2 FontData::get_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
+Vector2 FontFile::get_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
_ensure_rid(p_cache_index);
return TS->font_get_glyph_size(cache[p_cache_index], p_size, p_glyph);
}
-void FontData::set_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
+void FontFile::set_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_glyph_uv_rect(cache[p_cache_index], p_size, p_glyph, p_uv_rect);
}
-Rect2 FontData::get_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
+Rect2 FontFile::get_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(p_cache_index < 0, Rect2());
_ensure_rid(p_cache_index);
return TS->font_get_glyph_uv_rect(cache[p_cache_index], p_size, p_glyph);
}
-void FontData::set_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
+void FontFile::set_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_glyph_texture_idx(cache[p_cache_index], p_size, p_glyph, p_texture_idx);
}
-int FontData::get_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
+int FontFile::get_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
ERR_FAIL_COND_V(p_cache_index < 0, 0);
_ensure_rid(p_cache_index);
return TS->font_get_glyph_texture_idx(cache[p_cache_index], p_size, p_glyph);
}
-Array FontData::get_kerning_list(int p_cache_index, int p_size) const {
+Array FontFile::get_kerning_list(int p_cache_index, int p_size) const {
ERR_FAIL_COND_V(p_cache_index < 0, Array());
_ensure_rid(p_cache_index);
return TS->font_get_kerning_list(cache[p_cache_index], p_size);
}
-void FontData::clear_kerning_map(int p_cache_index, int p_size) {
+void FontFile::clear_kerning_map(int p_cache_index, int p_size) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_clear_kerning_map(cache[p_cache_index], p_size);
}
-void FontData::remove_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) {
+void FontFile::remove_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_remove_kerning(cache[p_cache_index], p_size, p_glyph_pair);
}
-void FontData::set_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
+void FontFile::set_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_set_kerning(cache[p_cache_index], p_size, p_glyph_pair, p_kerning);
}
-Vector2 FontData::get_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) const {
+Vector2 FontFile::get_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) const {
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
_ensure_rid(p_cache_index);
return TS->font_get_kerning(cache[p_cache_index], p_size, p_glyph_pair);
}
-void FontData::render_range(int p_cache_index, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
+void FontFile::render_range(int p_cache_index, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_render_range(cache[p_cache_index], p_size, p_start, p_end);
}
-void FontData::render_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_index) {
+void FontFile::render_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_index) {
ERR_FAIL_COND(p_cache_index < 0);
_ensure_rid(p_cache_index);
TS->font_render_glyph(cache[p_cache_index], p_size, p_index);
}
-RID FontData::get_cache_rid(int p_cache_index) const {
- ERR_FAIL_COND_V(p_cache_index < 0, RID());
- _ensure_rid(p_cache_index);
- return cache[p_cache_index];
-}
-
-bool FontData::is_language_supported(const String &p_language) const {
- _ensure_rid(0);
- return TS->font_is_language_supported(cache[0], p_language);
-}
-
-void FontData::set_language_support_override(const String &p_language, bool p_supported) {
+void FontFile::set_language_support_override(const String &p_language, bool p_supported) {
_ensure_rid(0);
TS->font_set_language_support_override(cache[0], p_language, p_supported);
}
-bool FontData::get_language_support_override(const String &p_language) const {
+bool FontFile::get_language_support_override(const String &p_language) const {
_ensure_rid(0);
return TS->font_get_language_support_override(cache[0], p_language);
}
-void FontData::remove_language_support_override(const String &p_language) {
+void FontFile::remove_language_support_override(const String &p_language) {
_ensure_rid(0);
TS->font_remove_language_support_override(cache[0], p_language);
}
-Vector<String> FontData::get_language_support_overrides() const {
+Vector<String> FontFile::get_language_support_overrides() const {
_ensure_rid(0);
return TS->font_get_language_support_overrides(cache[0]);
}
-bool FontData::is_script_supported(const String &p_script) const {
- _ensure_rid(0);
- return TS->font_is_script_supported(cache[0], p_script);
-}
-
-void FontData::set_script_support_override(const String &p_script, bool p_supported) {
+void FontFile::set_script_support_override(const String &p_script, bool p_supported) {
_ensure_rid(0);
TS->font_set_script_support_override(cache[0], p_script, p_supported);
}
-bool FontData::get_script_support_override(const String &p_script) const {
+bool FontFile::get_script_support_override(const String &p_script) const {
_ensure_rid(0);
return TS->font_get_script_support_override(cache[0], p_script);
}
-void FontData::remove_script_support_override(const String &p_script) {
+void FontFile::remove_script_support_override(const String &p_script) {
_ensure_rid(0);
TS->font_remove_script_support_override(cache[0], p_script);
}
-Vector<String> FontData::get_script_support_overrides() const {
+Vector<String> FontFile::get_script_support_overrides() const {
_ensure_rid(0);
return TS->font_get_script_support_overrides(cache[0]);
}
-void FontData::set_opentype_feature_overrides(const Dictionary &p_overrides) {
+void FontFile::set_opentype_feature_overrides(const Dictionary &p_overrides) {
_ensure_rid(0);
TS->font_set_opentype_feature_overrides(cache[0], p_overrides);
}
-Dictionary FontData::get_opentype_feature_overrides() const {
+Dictionary FontFile::get_opentype_feature_overrides() const {
_ensure_rid(0);
return TS->font_get_opentype_feature_overrides(cache[0]);
}
-bool FontData::has_char(char32_t p_char) const {
- _ensure_rid(0);
- return TS->font_has_char(cache[0], p_char);
-}
-
-String FontData::get_supported_chars() const {
- _ensure_rid(0);
- return TS->font_get_supported_chars(cache[0]);
-}
-
-int32_t FontData::get_glyph_index(int p_size, char32_t p_char, char32_t p_variation_selector) const {
+int32_t FontFile::get_glyph_index(int p_size, char32_t p_char, char32_t p_variation_selector) const {
_ensure_rid(0);
return TS->font_get_glyph_index(cache[0], p_size, p_char, p_variation_selector);
}
-Dictionary FontData::get_supported_feature_list() const {
- _ensure_rid(0);
- return TS->font_supported_feature_list(cache[0]);
-}
-
-Dictionary FontData::get_supported_variation_list() const {
- _ensure_rid(0);
- return TS->font_supported_variation_list(cache[0]);
-}
-
-FontData::FontData() {
+FontFile::FontFile() {
/* NOP */
}
-FontData::~FontData() {
- _clear_cache();
+FontFile::~FontFile() {
+ reset_state();
}
/*************************************************************************/
+/* FontVariation */
+/*************************************************************************/
-void Font::_data_changed() {
- for (int i = 0; i < rids.size(); i++) {
- rids.write[i] = RID();
- }
- emit_changed();
-}
-
-void Font::_ensure_rid(int p_index) const {
- // Find or create cache record.
- if (!rids[p_index].is_valid() && data[p_index].is_valid()) {
- rids.write[p_index] = data[p_index]->find_cache(variation_coordinates);
- }
-}
+void FontVariation::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_base_font", "font"), &FontVariation::set_base_font);
+ ClassDB::bind_method(D_METHOD("get_base_font"), &FontVariation::get_base_font);
-void Font::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_data", "data"), &Font::add_data);
- ClassDB::bind_method(D_METHOD("set_data", "idx", "data"), &Font::set_data);
- ClassDB::bind_method(D_METHOD("get_data_count"), &Font::get_data_count);
- ClassDB::bind_method(D_METHOD("get_data", "idx"), &Font::get_data);
- ClassDB::bind_method(D_METHOD("get_data_rid", "idx"), &Font::get_data_rid);
- 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_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");
-
- ClassDB::bind_method(D_METHOD("set_spacing", "spacing", "value"), &Font::set_spacing);
- ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
+ ClassDB::bind_method(D_METHOD("set_variation_opentype", "coords"), &FontVariation::set_variation_opentype);
+ ClassDB::bind_method(D_METHOD("get_variation_opentype"), &FontVariation::get_variation_opentype);
- ADD_GROUP("Extra Spacing", "spacing");
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
- ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
+ ClassDB::bind_method(D_METHOD("set_variation_embolden", "strength"), &FontVariation::set_variation_embolden);
+ ClassDB::bind_method(D_METHOD("get_variation_embolden"), &FontVariation::get_variation_embolden);
- 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("set_variation_face_index", "face_index"), &FontVariation::set_variation_face_index);
+ ClassDB::bind_method(D_METHOD("get_variation_face_index"), &FontVariation::get_variation_face_index);
- ClassDB::bind_method(D_METHOD("get_string_size", "text", "size", "alignment", "width", "flags"), &Font::get_string_size, DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(HORIZONTAL_ALIGNMENT_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("set_variation_transform", "transform"), &FontVariation::set_variation_transform);
+ ClassDB::bind_method(D_METHOD("get_variation_transform"), &FontVariation::get_variation_transform);
- ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_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", "alignment", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_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("set_opentype_features", "features"), &FontVariation::set_opentype_features);
- 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("set_spacing", "spacing", "value"), &FontVariation::set_spacing);
- ClassDB::bind_method(D_METHOD("has_char", "char"), &Font::has_char);
- ClassDB::bind_method(D_METHOD("get_supported_chars"), &Font::get_supported_chars);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_base_font", "get_base_font");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks");
- ClassDB::bind_method(D_METHOD("update_changes"), &Font::update_changes);
+ ADD_GROUP("Variation", "variation");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "variation_opentype"), "set_variation_opentype", "get_variation_opentype");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "variation_face_index"), "set_variation_face_index", "get_variation_face_index");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "variation_embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), "set_variation_embolden", "get_variation_embolden");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "variation_transform", PROPERTY_HINT_NONE, "suffix:px"), "set_variation_transform", "get_variation_transform");
- ClassDB::bind_method(D_METHOD("get_rids"), &Font::get_rids);
-}
+ ADD_GROUP("OpenType Features", "opentype");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_features"), "set_opentype_features", "get_opentype_features");
-bool Font::_set(const StringName &p_name, const Variant &p_value) {
- Vector<String> tokens = p_name.operator String().split("/");
-#ifndef DISABLE_DEPRECATED
- if (tokens.size() == 1 && tokens[0] == "font_data") {
- // Compatibility, DynamicFont main data.
- Ref<FontData> fd = p_value;
- if (fd.is_valid()) {
- add_data(fd);
- return true;
- }
- return false;
- } else if (tokens.size() == 2 && tokens[0] == "fallback") {
- // Compatibility, DynamicFont fallback data.
- Ref<FontData> fd = p_value;
- if (fd.is_valid()) {
- add_data(fd);
- return true;
- }
- return false;
- } else if (tokens.size() == 1 && tokens[0] == "fallback") {
- // Compatibility, BitmapFont fallback data.
- Ref<Font> f = p_value;
- if (f.is_valid()) {
- for (int i = 0; i < f->get_data_count(); i++) {
- add_data(f->get_data(i));
- }
- return true;
- }
- return false;
- }
-#endif /* DISABLE_DEPRECATED */
- if (tokens.size() == 2 && tokens[0] == "data") {
- int idx = tokens[1].to_int();
- Ref<FontData> fd = p_value;
- if (fd.is_valid()) {
- if (idx == data.size()) {
- add_data(fd);
- return true;
- } else if (idx >= 0 && idx < data.size()) {
- set_data(idx, fd);
- return true;
- } else {
- return false;
- }
- } else if (idx >= 0 && idx < data.size()) {
- remove_data(idx);
- return true;
- }
- }
- return false;
+ ADD_GROUP("Extra Spacing", "spacing");
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_glyph", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_GLYPH);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_space", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_SPACE);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
}
-bool Font::_get(const StringName &p_name, Variant &r_ret) const {
- Vector<String> tokens = p_name.operator String().split("/");
- if (tokens.size() == 2 && tokens[0] == "data") {
- int idx = tokens[1].to_int();
+void FontVariation::_update_rids() const {
+ Ref<Font> f = _get_base_font_or_default();
- if (idx == data.size()) {
- r_ret = Ref<FontData>();
- return true;
- } else if (idx >= 0 && idx < data.size()) {
- r_ret = get_data(idx);
- return true;
+ rids.clear();
+ if (fallbacks.is_empty() && f.is_valid()) {
+ RID rid = _get_rid();
+ if (rid.is_valid()) {
+ rids.push_back(rid);
}
- }
- return false;
-}
-
-void Font::_get_property_list(List<PropertyInfo> *p_list) const {
- for (int i = 0; i < data.size(); i++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "data/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "FontData"));
+ const TypedArray<Font> &base_fallbacks = f->get_fallbacks();
+ for (int i = 0; i < base_fallbacks.size(); i++) {
+ _update_rids_fb(base_fallbacks[i], 0);
+ }
+ } else {
+ _update_rids_fb(const_cast<FontVariation *>(this), 0);
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "data/" + itos(data.size()), PROPERTY_HINT_RESOURCE_TYPE, "FontData"));
+ dirty_rids = false;
}
-void Font::reset_state() {
- for (int i = 0; i < data.size(); i++) {
- if (data[i].is_valid()) {
- data.write[i]->connect(SNAME("changed"), callable_mp(this, &Font::_data_changed), varray(), CONNECT_REFERENCE_COUNTED);
- }
+void FontVariation::reset_state() {
+ if (base_font.is_valid()) {
+ base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
+ base_font.unref();
}
- cache.clear();
- cache_wrap.clear();
- data.clear();
- rids.clear();
-
- variation_coordinates.clear();
- spacing_bottom = 0;
- spacing_top = 0;
-}
-Dictionary Font::get_feature_list() const {
- Dictionary out;
- for (int i = 0; i < data.size(); i++) {
- Dictionary data_ftrs = data[i]->get_supported_feature_list();
- for (const Variant *ftr = data_ftrs.next(nullptr); ftr != nullptr; ftr = data_ftrs.next(ftr)) {
- out[*ftr] = data_ftrs[*ftr];
- }
+ if (theme_font.is_valid()) {
+ theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
+ theme_font.unref();
}
- return out;
-}
-void Font::add_data(const Ref<FontData> &p_data) {
- ERR_FAIL_COND(p_data.is_null());
- data.push_back(p_data);
- rids.push_back(RID());
+ variation = Variation();
+ opentype_features = Dictionary();
- if (data[data.size() - 1].is_valid()) {
- data.write[data.size() - 1]->connect(SNAME("changed"), callable_mp(this, &Font::_data_changed), varray(), CONNECT_REFERENCE_COUNTED);
- Dictionary data_var_list = p_data->get_supported_variation_list();
- for (int j = 0; j < data_var_list.size(); j++) {
- int32_t tag = data_var_list.get_key_at_index(j);
- Vector3i value = data_var_list.get_value_at_index(j);
- if (!variation_coordinates.has(tag) && !variation_coordinates.has(TS->tag_to_name(tag))) {
- variation_coordinates[TS->tag_to_name(tag)] = value.z;
- }
- }
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ extra_spacing[i] = 0;
}
- cache.clear();
- cache_wrap.clear();
-
- emit_changed();
- notify_property_list_changed();
+ Font::reset_state();
}
-void Font::set_data(int p_idx, const Ref<FontData> &p_data) {
- ERR_FAIL_COND(p_data.is_null());
- ERR_FAIL_INDEX(p_idx, data.size());
-
- if (data[p_idx].is_valid()) {
- data.write[p_idx]->disconnect(SNAME("changed"), callable_mp(this, &Font::_data_changed));
- }
-
- data.write[p_idx] = p_data;
- rids.write[p_idx] = RID();
- Dictionary data_var_list = p_data->get_supported_variation_list();
- for (int j = 0; j < data_var_list.size(); j++) {
- int32_t tag = data_var_list.get_key_at_index(j);
- Vector3i value = data_var_list.get_value_at_index(j);
- if (!variation_coordinates.has(tag) && !variation_coordinates.has(TS->tag_to_name(tag))) {
- variation_coordinates[TS->tag_to_name(tag)] = value.z;
+void FontVariation::set_base_font(const Ref<Font> &p_font) {
+ if (base_font != p_font) {
+ if (base_font.is_valid()) {
+ base_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
}
+ base_font = p_font;
+ if (base_font.is_valid()) {
+ base_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ _invalidate_rids();
+ notify_property_list_changed();
}
-
- if (data[p_idx].is_valid()) {
- data.write[p_idx]->connect(SNAME("changed"), callable_mp(this, &Font::_data_changed), varray(), CONNECT_REFERENCE_COUNTED);
- }
-
- cache.clear();
- cache_wrap.clear();
-
- emit_changed();
- notify_property_list_changed();
-}
-
-int Font::get_data_count() const {
- return data.size();
}
-Ref<FontData> Font::get_data(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, data.size(), Ref<FontData>());
- return data[p_idx];
+Ref<Font> FontVariation::get_base_font() const {
+ return base_font;
}
-RID Font::get_data_rid(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, data.size(), RID());
- _ensure_rid(p_idx);
- return rids[p_idx];
-}
-
-void Font::clear_data() {
- for (int i = 0; i < data.size(); i++) {
- if (data[i].is_valid()) {
- data.write[i]->connect(SNAME("changed"), callable_mp(this, &Font::_data_changed), varray(), CONNECT_REFERENCE_COUNTED);
- }
+Ref<Font> FontVariation::_get_base_font_or_default() const {
+ if (theme_font.is_valid()) {
+ theme_font->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids));
+ theme_font.unref();
}
- data.clear();
- rids.clear();
-}
-void Font::remove_data(int p_idx) {
- ERR_FAIL_INDEX(p_idx, data.size());
-
- if (data[p_idx].is_valid()) {
- data.write[p_idx]->disconnect(SNAME("changed"), callable_mp(this, &Font::_data_changed));
+ if (base_font.is_valid()) {
+ return base_font;
}
- data.remove_at(p_idx);
- rids.remove_at(p_idx);
-
- cache.clear();
- cache_wrap.clear();
+ // Check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ List<StringName> theme_types;
+ Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
- emit_changed();
- notify_property_list_changed();
-}
+ for (const StringName &E : theme_types) {
+ if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
+ Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
+ if (f.is_valid()) {
+ theme_font = f;
+ theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
+ }
+ }
+ }
-void Font::set_variation_coordinates(const Dictionary &p_variation_coordinates) {
- _data_changed();
- variation_coordinates = p_variation_coordinates;
-}
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ if (Theme::get_default().is_valid()) {
+ List<StringName> theme_types;
+ Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
-Dictionary Font::get_variation_coordinates() const {
- return variation_coordinates;
-}
+ for (const StringName &E : theme_types) {
+ if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
+ Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
+ if (f.is_valid()) {
+ theme_font = f;
+ theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
+ }
+ }
-void Font::set_spacing(TextServer::SpacingType p_spacing, int p_value) {
- _data_changed();
- switch (p_spacing) {
- case TextServer::SPACING_TOP: {
- spacing_top = p_value;
- } break;
- case TextServer::SPACING_BOTTOM: {
- spacing_bottom = p_value;
- } break;
- default: {
- ERR_FAIL_MSG("Invalid spacing type: " + itos(p_spacing));
- } break;
+ // If they don't exist, use any type to return the default/empty value.
+ Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
+ if (f.is_valid()) {
+ theme_font = f;
+ theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), varray(), CONNECT_REFERENCE_COUNTED);
+ }
+ return f;
}
-}
-int Font::get_spacing(TextServer::SpacingType p_spacing) const {
- switch (p_spacing) {
- case TextServer::SPACING_TOP: {
- return spacing_top;
- } break;
- case TextServer::SPACING_BOTTOM: {
- return spacing_bottom;
- } break;
- default: {
- ERR_FAIL_V_MSG(0, "Invalid spacing type: " + itos(p_spacing));
- } break;
- }
+ return Ref<Font>();
}
-real_t Font::get_height(int p_size) const {
- 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], p_size) + TS->font_get_descent(rids[i], p_size));
+void FontVariation::set_variation_opentype(const Dictionary &p_coords) {
+ if (variation.opentype != p_coords) {
+ variation.opentype = p_coords;
+ _invalidate_rids();
}
- return ret + spacing_bottom + spacing_top;
}
-real_t Font::get_ascent(int p_size) const {
- 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], p_size));
- }
- return ret + spacing_top;
+Dictionary FontVariation::get_variation_opentype() const {
+ return variation.opentype;
}
-real_t Font::get_descent(int p_size) const {
- 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], p_size));
+void FontVariation::set_variation_embolden(float p_strength) {
+ if (variation.embolden != p_strength) {
+ variation.embolden = p_strength;
+ _invalidate_rids();
}
- return ret + spacing_bottom;
}
-real_t Font::get_underline_position(int p_size) const {
- 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], p_size));
- }
- return ret + spacing_top;
+float FontVariation::get_variation_embolden() const {
+ return variation.embolden;
}
-real_t Font::get_underline_thickness(int p_size) const {
- 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], p_size));
+void FontVariation::set_variation_transform(Transform2D p_transform) {
+ if (variation.transform != p_transform) {
+ variation.transform = p_transform;
+ _invalidate_rids();
}
- return ret;
}
-Size2 Font::get_string_size(const String &p_text, int p_size, HorizontalAlignment p_alignment, float p_width, uint16_t p_flags) const {
- ERR_FAIL_COND_V(data.is_empty(), Size2());
-
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
- }
-
- uint64_t hash = p_text.hash64();
- if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
- hash = hash_djb2_one_64(p_flags, 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), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
- cache.insert(hash, buffer);
- }
- return buffer->get_size();
+Transform2D FontVariation::get_variation_transform() const {
+ return variation.transform;
}
-Size2 Font::get_multiline_string_size(const String &p_text, float p_width, int p_size, uint16_t p_flags) const {
- ERR_FAIL_COND_V(data.is_empty(), Size2());
-
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
+void FontVariation::set_variation_face_index(int p_face_index) {
+ if (variation.face_index != p_face_index) {
+ variation.face_index = p_face_index;
+ _invalidate_rids();
}
-
- uint64_t hash = p_text.hash64();
- uint64_t wrp_hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
- wrp_hash = hash_djb2_one_64(p_flags, 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), 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);
- }
-
- Size2 ret;
- for (int i = 0; i < lines_buffer->get_line_count(); i++) {
- Size2 line_size = lines_buffer->get_line_size(i);
- if (lines_buffer->get_orientation() == TextServer::ORIENTATION_HORIZONTAL) {
- ret.x = MAX(ret.x, line_size.x);
- ret.y += line_size.y;
- } else {
- ret.y = MAX(ret.y, line_size.y);
- ret.x += line_size.x;
- }
- }
- return ret;
}
-void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float 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());
-
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
- }
-
- uint64_t hash = p_text.hash64();
- if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
- hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
- hash = hash_djb2_one_64(p_flags, 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), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
- cache.insert(hash, buffer);
- }
-
- Vector2 ofs = p_pos;
- if (buffer->get_orientation() == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y -= buffer->get_line_ascent();
- } else {
- ofs.x -= buffer->get_line_ascent();
- }
-
- buffer->set_width(p_width);
- buffer->set_horizontal_alignment(p_alignment);
- buffer->set_flags(p_flags);
-
- if (p_outline_size > 0 && p_outline_modulate.a != 0.0f) {
- buffer->draw_outline(p_canvas_item, ofs, p_outline_size, p_outline_modulate);
- }
- buffer->draw(p_canvas_item, ofs, p_modulate);
+int FontVariation::get_variation_face_index() const {
+ return variation.face_index;
}
-void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, 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());
-
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
- }
-
- uint64_t hash = p_text.hash64();
- uint64_t wrp_hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash);
- wrp_hash = hash_djb2_one_64(p_flags, 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), 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);
- }
-
- lines_buffer->set_alignment(p_alignment);
-
- Vector2 lofs = p_pos;
- for (int i = 0; i < lines_buffer->get_line_count(); i++) {
- if (lines_buffer->get_orientation() == TextServer::ORIENTATION_HORIZONTAL) {
- if (i == 0) {
- lofs.y -= lines_buffer->get_line_ascent(0);
- }
- } else {
- if (i == 0) {
- lofs.x -= lines_buffer->get_line_ascent(0);
- }
- }
- if (p_width > 0) {
- lines_buffer->set_alignment(p_alignment);
- }
-
- if (p_outline_size > 0 && p_outline_modulate.a != 0.0f) {
- lines_buffer->draw_line_outline(p_canvas_item, lofs, i, p_outline_size, p_outline_modulate);
- }
- lines_buffer->draw_line(p_canvas_item, lofs, i, p_modulate);
-
- Size2 line_size = lines_buffer->get_line_size(i);
- if (lines_buffer->get_orientation() == TextServer::ORIENTATION_HORIZONTAL) {
- lofs.y += line_size.y;
- } else {
- lofs.x += line_size.x;
- }
-
- if ((p_max_lines > 0) && (i >= p_max_lines)) {
- return;
- }
+void FontVariation::set_opentype_features(const Dictionary &p_features) {
+ if (opentype_features != p_features) {
+ opentype_features = p_features;
+ _invalidate_rids();
}
}
-Size2 Font::get_char_size(char32_t p_char, char32_t p_next, int p_size) const {
- 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], 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], p_size, p_next, 0);
- ret.x -= TS->font_get_kerning(rids[i], p_size, Vector2i(glyph_a, glyph_b)).x;
- }
- return ret;
- }
- }
- return Size2();
+Dictionary FontVariation::get_opentype_features() const {
+ return opentype_features;
}
-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 {
- 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], 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], 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, p_size, p_outline_size, p_pos, glyph_a, p_outline_modulate);
- }
- TS->font_draw_glyph(rids[i], p_canvas_item, p_size, p_pos, glyph_a, p_modulate);
- return ret;
- }
+void FontVariation::set_spacing(TextServer::SpacingType p_spacing, int p_value) {
+ ERR_FAIL_INDEX((int)p_spacing, TextServer::SPACING_MAX);
+ if (extra_spacing[p_spacing] != p_value) {
+ extra_spacing[p_spacing] = p_value;
+ _invalidate_rids();
}
- return 0;
}
-bool Font::has_char(char32_t p_char) const {
- for (int i = 0; i < data.size(); i++) {
- if (data[i]->has_char(p_char)) {
- return true;
- }
- }
- return false;
+int FontVariation::get_spacing(TextServer::SpacingType p_spacing) const {
+ ERR_FAIL_INDEX_V((int)p_spacing, TextServer::SPACING_MAX, 0);
+ return extra_spacing[p_spacing];
}
-String Font::get_supported_chars() const {
- String chars;
- for (int i = 0; i < data.size(); i++) {
- String data_chars = data[i]->get_supported_chars();
- for (int j = 0; j < data_chars.length(); j++) {
- if (chars.find_char(data_chars[j]) == -1) {
- chars += data_chars[j];
- }
- }
+RID FontVariation::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform) const {
+ Ref<Font> f = _get_base_font_or_default();
+ if (f.is_valid()) {
+ return f->find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform);
}
- return chars;
+ return RID();
}
-Array Font::get_rids() const {
- Array _rids;
- for (int i = 0; i < data.size(); i++) {
- _ensure_rid(i);
- if (rids[i].is_valid()) {
- _rids.push_back(rids[i]);
- }
+RID FontVariation::_get_rid() const {
+ Ref<Font> f = _get_base_font_or_default();
+ if (f.is_valid()) {
+ return f->find_variation(variation.opentype, variation.face_index, variation.embolden, variation.transform);
}
- return _rids;
-}
-
-void Font::update_changes() {
- emit_changed();
+ return RID();
}
-Font::Font() {
- cache.set_capacity(128);
- cache_wrap.set_capacity(32);
+FontVariation::FontVariation() {
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ extra_spacing[i] = 0;
+ }
}
-Font::~Font() {
- clear_data();
- cache.clear();
- cache_wrap.clear();
+FontVariation::~FontVariation() {
+ reset_state();
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 950959e054..40b223b0f5 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -37,16 +37,108 @@
#include "scene/resources/texture.h"
#include "servers/text_server.h"
+class TextLine;
+class TextParagraph;
+
+/*************************************************************************/
+/* Font */
+/*************************************************************************/
+
+class Font : public Resource {
+ GDCLASS(Font, Resource);
+
+ // Shaped string cache.
+ mutable LRUCache<uint64_t, Ref<TextLine>> cache;
+ mutable LRUCache<uint64_t, Ref<TextParagraph>> cache_wrap;
+
+protected:
+ // Output.
+ mutable TypedArray<RID> rids;
+ mutable bool dirty_rids = true;
+
+ // Fallbacks.
+ static constexpr int MAX_FALLBACK_DEPTH = 64;
+ TypedArray<Font> fallbacks;
+
+ static void _bind_methods();
+
+ virtual void _update_rids_fb(const Ref<Font> &p_f, int p_depth) const;
+ virtual void _update_rids() const;
+ virtual bool _is_cyclic(const Ref<Font> &p_f, int p_depth) const;
+
+ virtual void reset_state() override;
+
+public:
+ virtual void _invalidate_rids();
+
+ static constexpr int DEFAULT_FONT_SIZE = 16;
+
+ // Fallbacks.
+ virtual void set_fallbacks(const TypedArray<Font> &p_fallbacks);
+ virtual TypedArray<Font> get_fallbacks() const;
+
+ // Output.
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D()) const { return RID(); };
+ virtual RID _get_rid() const { return RID(); };
+ virtual TypedArray<RID> get_rids() const;
+
+ // Font metrics.
+ virtual real_t get_height(int p_font_size) const;
+ virtual real_t get_ascent(int p_font_size) const;
+ virtual real_t get_descent(int p_font_size) const;
+ virtual real_t get_underline_position(int p_font_size) const;
+ virtual real_t get_underline_thickness(int p_font_size) const;
+
+ virtual String get_font_name() const;
+ virtual String get_font_style_name() const;
+ virtual uint32_t get_font_style() const;
+
+ virtual int get_spacing(TextServer::SpacingType p_spacing) const { return 0; };
+ virtual Dictionary get_opentype_features() const;
+
+ // Drawing string.
+ virtual void set_cache_capacity(int p_single_line, int p_multi_line);
+
+ virtual Size2 get_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+ virtual Size2 get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+
+ virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+ virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+
+ virtual void draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+ virtual void draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float p_width = -1, int p_font_size = DEFAULT_FONT_SIZE, int p_max_lines = -1, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL) const;
+
+ // Drawing char.
+ virtual Size2 get_char_size(char32_t p_char, int p_font_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
+ virtual real_t draw_char_outline(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size = DEFAULT_FONT_SIZE, int p_size = 1, const Color &p_modulate = Color(1.0, 1.0, 1.0)) const;
+
+ // Helper functions.
+ virtual bool has_char(char32_t p_char) const;
+ virtual String get_supported_chars() const;
+
+ virtual bool is_language_supported(const String &p_language) const;
+ virtual bool is_script_supported(const String &p_script) const;
+
+ virtual Dictionary get_supported_feature_list() const;
+ virtual Dictionary get_supported_variation_list() const;
+ virtual int64_t get_face_count() const;
+
+ Font();
+ ~Font();
+};
+
+/*************************************************************************/
+/* FontFile */
/*************************************************************************/
-class FontData : public Resource {
- GDCLASS(FontData, Resource);
+class FontFile : public Font {
+ GDCLASS(FontFile, Font);
RES_BASE_EXTENSION("fontdata");
// Font source data.
const uint8_t *data_ptr = nullptr;
size_t data_size = 0;
- int face_index = 0;
PackedByteArray data;
bool antialiased = true;
@@ -59,8 +151,11 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
- real_t embolden = 0.f;
- Transform2D transform;
+
+#ifndef DISABLE_DEPRECATED
+ real_t bmp_height = 0.0;
+ real_t bmp_ascent = 0.0;
+#endif
// Cache.
mutable Vector<RID> cache;
@@ -92,20 +187,10 @@ public:
virtual void set_data(const PackedByteArray &p_data);
virtual PackedByteArray get_data() const;
- virtual void set_face_index(int64_t p_index);
- virtual int64_t get_face_index() const;
-
- virtual int64_t get_face_count() const;
-
// Common properties.
virtual void set_font_name(const String &p_name);
- virtual String get_font_name() const;
-
virtual void set_font_style_name(const String &p_name);
- virtual String get_font_style_name() const;
-
virtual void set_font_style(uint32_t p_style);
- virtual uint32_t get_font_style() const;
virtual void set_antialiased(bool p_antialiased);
virtual bool is_antialiased() const;
@@ -134,17 +219,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
- virtual void set_embolden(float p_strength);
- virtual float get_embolden() const;
-
- virtual void set_transform(Transform2D p_transform);
- virtual Transform2D get_transform() const;
-
virtual void set_oversampling(real_t p_oversampling);
virtual real_t get_oversampling() const;
// Cache.
- virtual RID find_cache(const Dictionary &p_variation_coordinates) const;
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D()) const override;
+ virtual RID _get_rid() const override;
virtual int get_cache_count() const;
virtual void clear_cache();
@@ -157,23 +237,29 @@ public:
virtual void set_variation_coordinates(int p_cache_index, const Dictionary &p_variation_coordinates);
virtual Dictionary get_variation_coordinates(int p_cache_index) const;
- virtual void set_ascent(int p_cache_index, int p_size, real_t p_ascent);
- virtual real_t get_ascent(int p_cache_index, int p_size) const;
+ virtual void set_embolden(int p_cache_index, float p_strength);
+ virtual float get_embolden(int p_cache_index) const;
+
+ virtual void set_transform(int p_cache_index, Transform2D p_transform);
+ virtual Transform2D get_transform(int p_cache_index) const;
+
+ virtual void set_face_index(int p_cache_index, int64_t p_index);
+ virtual int64_t get_face_index(int p_cache_index) const;
- virtual void set_descent(int p_cache_index, int p_size, real_t p_descent);
- virtual real_t get_descent(int p_cache_index, int p_size) const;
+ virtual void set_cache_ascent(int p_cache_index, int p_size, real_t p_ascent);
+ virtual real_t get_cache_ascent(int p_cache_index, int p_size) const;
- virtual void set_underline_position(int p_cache_index, int p_size, real_t p_underline_position);
- virtual real_t get_underline_position(int p_cache_index, int p_size) const;
+ virtual void set_cache_descent(int p_cache_index, int p_size, real_t p_descent);
+ virtual real_t get_cache_descent(int p_cache_index, int p_size) const;
- virtual void set_underline_thickness(int p_cache_index, int p_size, real_t p_underline_thickness);
- virtual real_t get_underline_thickness(int p_cache_index, int p_size) const;
+ virtual void set_cache_underline_position(int p_cache_index, int p_size, real_t p_underline_position);
+ virtual real_t get_cache_underline_position(int p_cache_index, int p_size) const;
- virtual void set_scale(int p_cache_index, int p_size, real_t p_scale); // Rendering scale for bitmap fonts (e.g. emoji fonts).
- virtual real_t get_scale(int p_cache_index, int p_size) const;
+ virtual void set_cache_underline_thickness(int p_cache_index, int p_size, real_t p_underline_thickness);
+ virtual real_t get_cache_underline_thickness(int p_cache_index, int p_size) const;
- virtual void set_spacing(int p_cache_index, int p_size, TextServer::SpacingType p_spacing, int p_value);
- virtual int get_spacing(int p_cache_index, int p_size, TextServer::SpacingType p_spacing) const;
+ virtual void set_cache_scale(int p_cache_index, int p_size, real_t p_scale); // Rendering scale for bitmap fonts (e.g. emoji fonts).
+ virtual real_t get_cache_scale(int p_cache_index, int p_size) const;
virtual int get_texture_count(int p_cache_index, const Vector2i &p_size) const;
virtual void clear_textures(int p_cache_index, const Vector2i &p_size);
@@ -214,16 +300,12 @@ public:
virtual void render_range(int p_cache_index, const Vector2i &p_size, char32_t p_start, char32_t p_end);
virtual void render_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_index);
- virtual RID get_cache_rid(int p_cache_index) const;
-
// Language/script support override.
- virtual bool is_language_supported(const String &p_language) const;
virtual void set_language_support_override(const String &p_language, bool p_supported);
virtual bool get_language_support_override(const String &p_language) const;
virtual void remove_language_support_override(const String &p_language);
virtual Vector<String> get_language_support_overrides() const;
- virtual bool is_script_supported(const String &p_script) const;
virtual void set_script_support_override(const String &p_script, bool p_supported);
virtual bool get_script_support_override(const String &p_script) const;
virtual void remove_script_support_override(const String &p_script);
@@ -233,100 +315,70 @@ public:
virtual Dictionary get_opentype_feature_overrides() const;
// Base font properties.
- virtual bool has_char(char32_t p_char) const;
- virtual String get_supported_chars() const;
-
virtual int32_t get_glyph_index(int p_size, char32_t p_char, char32_t p_variation_selector = 0x0000) const;
- virtual Dictionary get_supported_feature_list() const;
- virtual Dictionary get_supported_variation_list() const;
-
- FontData();
- ~FontData();
+ FontFile();
+ ~FontFile();
};
/*************************************************************************/
+/* FontVariation */
+/*************************************************************************/
-class TextLine;
-class TextParagraph;
+class FontVariation : public Font {
+ GDCLASS(FontVariation, Font);
-class Font : public Resource {
- GDCLASS(Font, Resource);
+ struct Variation {
+ Dictionary opentype;
+ real_t embolden = 0.f;
+ int face_index = 0;
+ Transform2D transform;
+ };
- // Shaped string cache.
- mutable LRUCache<uint64_t, Ref<TextLine>> cache;
- mutable LRUCache<uint64_t, Ref<TextParagraph>> cache_wrap;
-
- // Font data cache.
- Vector<Ref<FontData>> data;
- mutable Vector<RID> rids;
+ mutable Ref<Font> theme_font;
- // Font config.
- Dictionary variation_coordinates;
- int spacing_bottom = 0;
- int spacing_top = 0;
+ Ref<Font> base_font;
- _FORCE_INLINE_ void _data_changed();
- _FORCE_INLINE_ void _ensure_rid(int p_index) const; // Find or create cache record.
+ Variation variation;
+ Dictionary opentype_features;
+ int extra_spacing[TextServer::SPACING_MAX];
protected:
static void _bind_methods();
- 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;
+ virtual void _update_rids() const override;
virtual void reset_state() override;
public:
- static const int DEFAULT_FONT_SIZE = 16;
-
- Dictionary get_feature_list() const;
+ virtual void set_base_font(const Ref<Font> &p_font);
+ virtual Ref<Font> get_base_font() const;
+ virtual Ref<Font> _get_base_font_or_default() const;
- // Font data.
- virtual void add_data(const Ref<FontData> &p_data);
- virtual void set_data(int p_idx, const Ref<FontData> &p_data);
- virtual int get_data_count() const;
- virtual Ref<FontData> get_data(int p_idx) const;
- virtual RID get_data_rid(int p_idx) const;
- virtual void clear_data();
- virtual void remove_data(int p_idx);
+ virtual void set_variation_opentype(const Dictionary &p_coords);
+ virtual Dictionary get_variation_opentype() const;
- // Font configuration.
- virtual void set_variation_coordinates(const Dictionary &p_variation_coordinates);
- virtual Dictionary get_variation_coordinates() const;
+ virtual void set_variation_embolden(float p_strength);
+ virtual float get_variation_embolden() const;
- virtual void set_spacing(TextServer::SpacingType p_spacing, int p_value);
- virtual int get_spacing(TextServer::SpacingType p_spacing) const;
-
- // Font metrics.
- 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;
+ virtual void set_variation_transform(Transform2D p_transform);
+ virtual Transform2D get_variation_transform() const;
- // Drawing string.
- virtual Size2 get_string_size(const String &p_text, int p_size = DEFAULT_FONT_SIZE, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float 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, float p_width = -1, int p_size = DEFAULT_FONT_SIZE, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) const;
+ virtual void set_variation_face_index(int p_face_index);
+ virtual int get_variation_face_index() const;
- virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float 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, HorizontalAlignment p_alignment = HORIZONTAL_ALIGNMENT_LEFT, float 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;
+ virtual void set_opentype_features(const Dictionary &p_features);
+ virtual Dictionary get_opentype_features() const override;
- // 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 = 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;
-
- Array get_rids() const;
+ virtual void set_spacing(TextServer::SpacingType p_spacing, int p_value);
+ virtual int get_spacing(TextServer::SpacingType p_spacing) const override;
- void update_changes();
+ // Output.
+ virtual RID find_variation(const Dictionary &p_variation_coordinates, int p_face_index = 0, float p_strength = 0.0, Transform2D p_transform = Transform2D()) const override;
+ virtual RID _get_rid() const override;
- Font();
- ~Font();
+ FontVariation();
+ ~FontVariation();
};
#endif /* FONT_H */
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index f4fd81b25f..68441afb1c 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -2190,12 +2190,12 @@ RibbonTrailMesh::RibbonTrailMesh() {
/* TextMesh */
/*************************************************************************/
-void TextMesh::_generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_gl) const {
- if (cache.has(p_hash)) {
+void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const {
+ if (cache.has(p_key)) {
return;
}
- GlyphMeshData &gl_data = cache[p_hash];
+ GlyphMeshData &gl_data = cache[p_key];
Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index);
Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size;
@@ -2376,7 +2376,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
TS->shaped_text_set_direction(text_rid, text_direction);
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
- TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language);
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
Array stt;
if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
@@ -2394,7 +2397,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
} else if (dirty_font) {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
- TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
+ }
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
dirty_font = false;
@@ -2437,11 +2443,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
continue;
}
if (glyphs[i].font_rid != RID()) {
- uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
- hash = hash_murmur3_one_32(glyphs[i].index, hash);
-
- _generate_glyph_mesh_data(hash, glyphs[i]);
- GlyphMeshData &gl_data = cache[hash];
+ GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
+ _generate_glyph_mesh_data(key, glyphs[i]);
+ GlyphMeshData &gl_data = cache[key];
p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
@@ -2496,10 +2500,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
continue;
}
if (glyphs[i].font_rid != RID()) {
- uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
- hash = hash_murmur3_one_32(glyphs[i].index, hash);
-
- const GlyphMeshData &gl_data = cache[hash];
+ GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
+ _generate_glyph_mesh_data(key, glyphs[i]);
+ const GlyphMeshData &gl_data = cache[key];
int64_t ts = gl_data.triangles.size();
const Vector2 *ts_ptr = gl_data.triangles.ptr();
@@ -2682,10 +2685,6 @@ void TextMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextMesh::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &TextMesh::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &TextMesh::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &TextMesh::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &TextMesh::clear_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_language", "language"), &TextMesh::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &TextMesh::get_language);
@@ -2704,11 +2703,9 @@ void TextMesh::_bind_methods() {
ADD_GROUP("Text", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1,suffix:px"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
ADD_GROUP("Mesh", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
@@ -2716,9 +2713,11 @@ void TextMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width");
- ADD_GROUP("Locale", "");
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
void TextMesh::_notification(int p_what) {
@@ -2735,56 +2734,6 @@ void TextMesh::_notification(int p_what) {
}
}
-bool TextMesh::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- dirty_font = true;
- _request_update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- dirty_font = true;
- _request_update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool TextMesh::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void TextMesh::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
TextMesh::TextMesh() {
primitive_type = PRIMITIVE_TRIANGLES;
text_rid = TS->create_shaped_text();
@@ -2848,7 +2797,7 @@ Ref<Font> TextMesh::get_font() const {
}
Ref<Font> TextMesh::_get_font_or_default() const {
- if (font_override.is_valid() && font_override->get_data_count() > 0) {
+ if (font_override.is_valid()) {
return font_override;
}
@@ -2955,29 +2904,6 @@ TextServer::Direction TextMesh::get_text_direction() const {
return text_direction;
}
-void TextMesh::clear_opentype_features() {
- opentype_features.clear();
- dirty_font = true;
- _request_update();
-}
-
-void TextMesh::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- dirty_font = true;
- _request_update();
- }
-}
-
-int TextMesh::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void TextMesh::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 38cc7db5fe..cb93211756 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -475,6 +475,7 @@ private:
sharp = p_sharp;
};
};
+
struct ContourInfo {
real_t length = 0.0;
bool ccw = true;
@@ -484,6 +485,27 @@ private:
ccw = p_ccw;
}
};
+
+ struct GlyphMeshKey {
+ uint64_t font_id;
+ uint32_t gl_id;
+
+ bool operator==(const GlyphMeshKey &p_b) const {
+ return (font_id == p_b.font_id) && (gl_id == p_b.gl_id);
+ }
+
+ GlyphMeshKey(uint64_t p_font_id, uint32_t p_gl_id) {
+ font_id = p_font_id;
+ gl_id = p_gl_id;
+ }
+ };
+
+ struct GlyphMeshKeyHasher {
+ _FORCE_INLINE_ static uint32_t hash(const GlyphMeshKey &p_a) {
+ return hash_murmur3_buffer(&p_a, sizeof(GlyphMeshKey));
+ }
+ };
+
struct GlyphMeshData {
Vector<Vector2> triangles;
Vector<Vector<ContourPoint>> contours;
@@ -491,7 +513,7 @@ private:
Vector2 min_p = Vector2(INFINITY, INFINITY);
Vector2 max_p = Vector2(-INFINITY, -INFINITY);
};
- mutable HashMap<uint32_t, GlyphMeshData> cache;
+ mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache;
RID text_rid;
String text;
@@ -503,7 +525,6 @@ private:
HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;
bool uppercase = false;
- Dictionary opentype_features;
String language;
TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
@@ -517,7 +538,7 @@ private:
mutable bool dirty_font = true;
mutable bool dirty_cache = true;
- void _generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_glyph) const;
+ void _generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_glyph) const;
void _font_changed();
protected:
@@ -526,10 +547,6 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
- 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;
-
public:
GDVIRTUAL2RC(Array, _structured_text_parser, Array, String)
@@ -552,10 +569,6 @@ public:
void set_text_direction(TextServer::Direction p_text_direction);
TextServer::Direction get_text_direction() const;
- void set_opentype_feature(const String &p_name, int p_value);
- int get_opentype_feature(const String &p_name) const;
- void clear_opentype_features();
-
void set_language(const String &p_language);
String get_language() const;
diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp
new file mode 100644
index 0000000000..05d48f9545
--- /dev/null
+++ b/scene/resources/skeleton_profile.cpp
@@ -0,0 +1,514 @@
+/*************************************************************************/
+/* skeleton_profile.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "skeleton_profile.h"
+
+bool SkeletonProfile::_set(const StringName &p_path, const Variant &p_value) {
+ ERR_FAIL_COND_V(is_read_only, false);
+ String path = p_path;
+
+ if (path.begins_with("group/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, groups.size(), false);
+
+ if (what == "group_name") {
+ set_group_name(which, p_value);
+ } else if (what == "texture") {
+ set_texture(which, p_value);
+ }
+ return true;
+ }
+
+ if (path.begins_with("bone/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, bones.size(), false);
+
+ if (what == "bone_name") {
+ set_bone_name(which, p_value);
+ } else if (what == "handle_offset") {
+ set_handle_offset(which, p_value);
+ } else if (what == "group") {
+ set_group(which, p_value);
+ }
+ return true;
+ }
+ return true;
+}
+
+bool SkeletonProfile::_get(const StringName &p_path, Variant &r_ret) const {
+ String path = p_path;
+
+ if (path.begins_with("group/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, groups.size(), false);
+
+ if (what == "group_name") {
+ r_ret = get_group_name(which);
+ } else if (what == "texture") {
+ r_ret = get_texture(which);
+ }
+ return true;
+ }
+
+ if (path.begins_with("bone/")) {
+ int which = path.get_slicec('/', 1).to_int();
+ String what = path.get_slicec('/', 2);
+ ERR_FAIL_INDEX_V(which, bones.size(), false);
+
+ if (what == "bone_name") {
+ r_ret = get_bone_name(which);
+ } else if (what == "handle_offset") {
+ r_ret = get_handle_offset(which);
+ } else if (what == "group") {
+ r_ret = get_group(which);
+ }
+ return true;
+ }
+ return true;
+}
+
+void SkeletonProfile::_validate_property(PropertyInfo &property) const {
+ if (is_read_only) {
+ if (property.name == ("group_size") || property.name == ("bone_size")) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ return;
+ }
+ }
+}
+
+void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (is_read_only) {
+ return;
+ }
+ String group_names = "";
+ for (int i = 0; i < groups.size(); i++) {
+ String path = "group/" + itos(i) + "/";
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "group_name"));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, path + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"));
+ if (i > 0) {
+ group_names = group_names + ",";
+ }
+ group_names = group_names + groups[i].group_name;
+ }
+ for (int i = 0; i < bones.size(); i++) {
+ String path = "bone/" + itos(i) + "/";
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_name"));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2, path + "handle_offset"));
+ p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "group", PROPERTY_HINT_ENUM, group_names));
+ }
+}
+
+int SkeletonProfile::get_group_size() {
+ return groups.size();
+}
+
+void SkeletonProfile::set_group_size(int p_size) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_COND(p_size < 0);
+ groups.resize(p_size);
+ emit_signal("profile_updated");
+ notify_property_list_changed();
+}
+
+StringName SkeletonProfile::get_group_name(int p_group_idx) const {
+ ERR_FAIL_INDEX_V(p_group_idx, groups.size(), StringName());
+ return groups[p_group_idx].group_name;
+}
+
+void SkeletonProfile::set_group_name(int p_group_idx, const StringName p_group_name) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_group_idx, groups.size());
+ groups.write[p_group_idx].group_name = p_group_name;
+ emit_signal("profile_updated");
+}
+
+Ref<Texture2D> SkeletonProfile::get_texture(int p_group_idx) const {
+ ERR_FAIL_INDEX_V(p_group_idx, groups.size(), Ref<Texture2D>());
+ return groups[p_group_idx].texture;
+}
+
+void SkeletonProfile::set_texture(int p_group_idx, const Ref<Texture2D> &p_texture) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_group_idx, groups.size());
+ groups.write[p_group_idx].texture = p_texture;
+ emit_signal("profile_updated");
+}
+
+int SkeletonProfile::get_bone_size() {
+ return bones.size();
+}
+
+void SkeletonProfile::set_bone_size(int p_size) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_COND(p_size < 0);
+ bones.resize(p_size);
+ emit_signal("profile_updated");
+ notify_property_list_changed();
+}
+
+StringName SkeletonProfile::get_bone_name(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName());
+ return bones[p_bone_idx].bone_name;
+}
+
+void SkeletonProfile::set_bone_name(int p_bone_idx, const StringName p_bone_name) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].bone_name = p_bone_name;
+ emit_signal("profile_updated");
+}
+
+Vector2 SkeletonProfile::get_handle_offset(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), Vector2());
+ return bones[p_bone_idx].handle_offset;
+}
+
+void SkeletonProfile::set_handle_offset(int p_bone_idx, const Vector2 p_handle_offset) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].handle_offset = p_handle_offset;
+ emit_signal("profile_updated");
+}
+
+StringName SkeletonProfile::get_group(int p_bone_idx) const {
+ ERR_FAIL_INDEX_V(p_bone_idx, bones.size(), StringName());
+ return bones[p_bone_idx].group;
+}
+
+void SkeletonProfile::set_group(int p_bone_idx, const StringName p_group) {
+ if (is_read_only) {
+ return;
+ }
+ ERR_FAIL_INDEX(p_bone_idx, bones.size());
+ bones.write[p_bone_idx].group = p_group;
+ emit_signal("profile_updated");
+}
+
+bool SkeletonProfile::has_bone(StringName p_bone_name) {
+ bool is_found = false;
+ for (int i = 0; i < bones.size(); i++) {
+ if (bones[i].bone_name == p_bone_name) {
+ is_found = true;
+ break;
+ }
+ }
+ return is_found;
+}
+
+void SkeletonProfile::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_group_size", "size"), &SkeletonProfile::set_group_size);
+ ClassDB::bind_method(D_METHOD("get_group_size"), &SkeletonProfile::get_group_size);
+
+ ClassDB::bind_method(D_METHOD("get_group_name", "group_idx"), &SkeletonProfile::get_group_name);
+ ClassDB::bind_method(D_METHOD("set_group_name", "group_idx", "group_name"), &SkeletonProfile::set_group_name);
+
+ ClassDB::bind_method(D_METHOD("get_texture", "group_idx"), &SkeletonProfile::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture", "group_idx", "texture"), &SkeletonProfile::set_texture);
+
+ ClassDB::bind_method(D_METHOD("set_bone_size", "size"), &SkeletonProfile::set_bone_size);
+ ClassDB::bind_method(D_METHOD("get_bone_size"), &SkeletonProfile::get_bone_size);
+
+ ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &SkeletonProfile::get_bone_name);
+ ClassDB::bind_method(D_METHOD("set_bone_name", "bone_idx", "bone_name"), &SkeletonProfile::set_bone_name);
+
+ ClassDB::bind_method(D_METHOD("get_handle_offset", "bone_idx"), &SkeletonProfile::get_handle_offset);
+ ClassDB::bind_method(D_METHOD("set_handle_offset", "bone_idx", "handle_offset"), &SkeletonProfile::set_handle_offset);
+
+ ClassDB::bind_method(D_METHOD("get_group", "bone_idx"), &SkeletonProfile::get_group);
+ ClassDB::bind_method(D_METHOD("set_group", "bone_idx", "group"), &SkeletonProfile::set_group);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "group_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Groups,group/"), "set_group_size", "get_group_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_size", PROPERTY_HINT_RANGE, "0,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Bones,bone/"), "set_bone_size", "get_bone_size");
+
+ ADD_SIGNAL(MethodInfo("profile_updated"));
+}
+
+SkeletonProfile::SkeletonProfile() {
+}
+
+SkeletonProfile::~SkeletonProfile() {
+}
+
+SkeletonProfileHumanoid::SkeletonProfileHumanoid() {
+ is_read_only = true;
+
+ groups.resize(4);
+
+ groups.write[0].group_name = "Body";
+ groups.write[1].group_name = "Face";
+ groups.write[2].group_name = "LeftHand";
+ groups.write[3].group_name = "RightHand";
+
+ bones.resize(56);
+
+ bones.write[0].bone_name = "Root";
+ bones.write[0].handle_offset = Vector2(0.5, 0.91);
+ bones.write[0].group = "Body";
+
+ bones.write[1].bone_name = "Hips";
+ bones.write[1].handle_offset = Vector2(0.5, 0.5);
+ bones.write[1].group = "Body";
+
+ bones.write[2].bone_name = "Spine";
+ bones.write[2].handle_offset = Vector2(0.5, 0.43);
+ bones.write[2].group = "Body";
+
+ bones.write[3].bone_name = "Chest";
+ bones.write[3].handle_offset = Vector2(0.5, 0.36);
+ bones.write[3].group = "Body";
+
+ bones.write[4].bone_name = "UpperChest";
+ bones.write[4].handle_offset = Vector2(0.5, 0.29);
+ bones.write[4].group = "Body";
+
+ bones.write[5].bone_name = "Neck";
+ bones.write[5].handle_offset = Vector2(0.5, 0.23);
+ bones.write[5].group = "Body";
+
+ bones.write[6].bone_name = "Head";
+ bones.write[6].handle_offset = Vector2(0.5, 0.18);
+ bones.write[6].group = "Body";
+
+ bones.write[7].bone_name = "LeftEye";
+ bones.write[7].handle_offset = Vector2(0.6, 0.46);
+ bones.write[7].group = "Face";
+
+ bones.write[8].bone_name = "RightEye";
+ bones.write[8].handle_offset = Vector2(0.37, 0.46);
+ bones.write[8].group = "Face";
+
+ bones.write[9].bone_name = "Jaw";
+ bones.write[9].handle_offset = Vector2(0.46, 0.75);
+ bones.write[9].group = "Face";
+
+ bones.write[10].bone_name = "LeftShoulder";
+ bones.write[10].handle_offset = Vector2(0.55, 0.235);
+ bones.write[10].group = "Body";
+
+ bones.write[11].bone_name = "LeftUpperArm";
+ bones.write[11].handle_offset = Vector2(0.6, 0.24);
+ bones.write[11].group = "Body";
+
+ bones.write[12].bone_name = "LeftLowerArm";
+ bones.write[12].handle_offset = Vector2(0.7, 0.24);
+ bones.write[12].group = "Body";
+
+ bones.write[13].bone_name = "LeftHand";
+ bones.write[13].handle_offset = Vector2(0.82, 0.235);
+ bones.write[13].group = "Body";
+
+ bones.write[14].bone_name = "LeftThumbProximal";
+ bones.write[14].handle_offset = Vector2(0.4, 0.8);
+ bones.write[14].group = "LeftHand";
+
+ bones.write[15].bone_name = "LeftThumbIntermediate";
+ bones.write[15].handle_offset = Vector2(0.3, 0.69);
+ bones.write[15].group = "LeftHand";
+
+ bones.write[16].bone_name = "LeftThumbDistal";
+ bones.write[16].handle_offset = Vector2(0.23, 0.555);
+ bones.write[16].group = "LeftHand";
+
+ bones.write[17].bone_name = "LeftIndexProximal";
+ bones.write[17].handle_offset = Vector2(0.413, 0.52);
+ bones.write[17].group = "LeftHand";
+
+ bones.write[18].bone_name = "LeftIndexIntermediate";
+ bones.write[18].handle_offset = Vector2(0.403, 0.36);
+ bones.write[18].group = "LeftHand";
+
+ bones.write[19].bone_name = "LeftIndexDistal";
+ bones.write[19].handle_offset = Vector2(0.403, 0.255);
+ bones.write[19].group = "LeftHand";
+
+ bones.write[20].bone_name = "LeftMiddleProximal";
+ bones.write[20].handle_offset = Vector2(0.5, 0.51);
+ bones.write[20].group = "LeftHand";
+
+ bones.write[21].bone_name = "LeftMiddleIntermediate";
+ bones.write[21].handle_offset = Vector2(0.5, 0.345);
+ bones.write[21].group = "LeftHand";
+
+ bones.write[22].bone_name = "LeftMiddleDistal";
+ bones.write[22].handle_offset = Vector2(0.5, 0.22);
+ bones.write[22].group = "LeftHand";
+
+ bones.write[23].bone_name = "LeftRingProximal";
+ bones.write[23].handle_offset = Vector2(0.586, 0.52);
+ bones.write[23].group = "LeftHand";
+
+ bones.write[24].bone_name = "LeftRingIntermediate";
+ bones.write[24].handle_offset = Vector2(0.59, 0.36);
+ bones.write[24].group = "LeftHand";
+
+ bones.write[25].bone_name = "LeftRingDistal";
+ bones.write[25].handle_offset = Vector2(0.591, 0.25);
+ bones.write[25].group = "LeftHand";
+
+ bones.write[26].bone_name = "LeftLittleProximal";
+ bones.write[26].handle_offset = Vector2(0.663, 0.543);
+ bones.write[26].group = "LeftHand";
+
+ bones.write[27].bone_name = "LeftLittleIntermediate";
+ bones.write[27].handle_offset = Vector2(0.672, 0.415);
+ bones.write[27].group = "LeftHand";
+
+ bones.write[28].bone_name = "LeftLittleDistal";
+ bones.write[28].handle_offset = Vector2(0.672, 0.32);
+ bones.write[28].group = "LeftHand";
+
+ bones.write[29].bone_name = "RightShoulder";
+ bones.write[29].handle_offset = Vector2(0.45, 0.235);
+ bones.write[29].group = "Body";
+
+ bones.write[30].bone_name = "RightUpperArm";
+ bones.write[30].handle_offset = Vector2(0.4, 0.24);
+ bones.write[30].group = "Body";
+
+ bones.write[31].bone_name = "RightLowerArm";
+ bones.write[31].handle_offset = Vector2(0.3, 0.24);
+ bones.write[31].group = "Body";
+
+ bones.write[32].bone_name = "RightHand";
+ bones.write[32].handle_offset = Vector2(0.18, 0.235);
+ bones.write[32].group = "Body";
+
+ bones.write[33].bone_name = "RightThumbProximal";
+ bones.write[33].handle_offset = Vector2(0.6, 0.8);
+ bones.write[33].group = "RightHand";
+
+ bones.write[34].bone_name = "RightThumbIntermediate";
+ bones.write[34].handle_offset = Vector2(0.7, 0.69);
+ bones.write[34].group = "RightHand";
+
+ bones.write[35].bone_name = "RightThumbDistal";
+ bones.write[35].handle_offset = Vector2(0.77, 0.555);
+ bones.write[35].group = "RightHand";
+
+ bones.write[36].bone_name = "RightIndexProximal";
+ bones.write[36].handle_offset = Vector2(0.587, 0.52);
+ bones.write[36].group = "RightHand";
+
+ bones.write[37].bone_name = "RightIndexIntermediate";
+ bones.write[37].handle_offset = Vector2(0.597, 0.36);
+ bones.write[37].group = "RightHand";
+
+ bones.write[38].bone_name = "RightIndexDistal";
+ bones.write[38].handle_offset = Vector2(0.597, 0.255);
+ bones.write[38].group = "RightHand";
+
+ bones.write[39].bone_name = "RightMiddleProximal";
+ bones.write[39].handle_offset = Vector2(0.5, 0.51);
+ bones.write[39].group = "RightHand";
+
+ bones.write[40].bone_name = "RightMiddleIntermediate";
+ bones.write[40].handle_offset = Vector2(0.5, 0.345);
+ bones.write[40].group = "RightHand";
+
+ bones.write[41].bone_name = "RightMiddleDistal";
+ bones.write[41].handle_offset = Vector2(0.5, 0.22);
+ bones.write[41].group = "RightHand";
+
+ bones.write[42].bone_name = "RightRingProximal";
+ bones.write[42].handle_offset = Vector2(0.414, 0.52);
+ bones.write[42].group = "RightHand";
+
+ bones.write[43].bone_name = "RightRingIntermediate";
+ bones.write[43].handle_offset = Vector2(0.41, 0.36);
+ bones.write[43].group = "RightHand";
+
+ bones.write[44].bone_name = "RightRingDistal";
+ bones.write[44].handle_offset = Vector2(0.409, 0.25);
+ bones.write[44].group = "RightHand";
+
+ bones.write[45].bone_name = "RightLittleProximal";
+ bones.write[45].handle_offset = Vector2(0.337, 0.543);
+ bones.write[45].group = "RightHand";
+
+ bones.write[46].bone_name = "RightLittleIntermediate";
+ bones.write[46].handle_offset = Vector2(0.328, 0.415);
+ bones.write[46].group = "RightHand";
+
+ bones.write[47].bone_name = "RightLittleDistal";
+ bones.write[47].handle_offset = Vector2(0.328, 0.32);
+ bones.write[47].group = "RightHand";
+
+ bones.write[48].bone_name = "LeftUpperLeg";
+ bones.write[48].handle_offset = Vector2(0.549, 0.49);
+ bones.write[48].group = "Body";
+
+ bones.write[49].bone_name = "LeftLowerLeg";
+ bones.write[49].handle_offset = Vector2(0.548, 0.683);
+ bones.write[49].group = "Body";
+
+ bones.write[50].bone_name = "LeftFoot";
+ bones.write[50].handle_offset = Vector2(0.545, 0.9);
+ bones.write[50].group = "Body";
+
+ bones.write[51].bone_name = "LeftToes";
+ bones.write[51].handle_offset = Vector2(0.545, 0.95);
+ bones.write[51].group = "Body";
+
+ bones.write[52].bone_name = "RightUpperLeg";
+ bones.write[52].handle_offset = Vector2(0.451, 0.49);
+ bones.write[52].group = "Body";
+
+ bones.write[53].bone_name = "RightLowerLeg";
+ bones.write[53].handle_offset = Vector2(0.452, 0.683);
+ bones.write[53].group = "Body";
+
+ bones.write[54].bone_name = "RightFoot";
+ bones.write[54].handle_offset = Vector2(0.455, 0.9);
+ bones.write[54].group = "Body";
+
+ bones.write[55].bone_name = "RightToes";
+ bones.write[55].handle_offset = Vector2(0.455, 0.95);
+ bones.write[55].group = "Body";
+}
+
+SkeletonProfileHumanoid::~SkeletonProfileHumanoid() {
+}
+
+//////////////////////////////////////
diff --git a/editor/plugins/ot_features_plugin.h b/scene/resources/skeleton_profile.h
index 6639148080..920aaa2b8d 100644
--- a/editor/plugins/ot_features_plugin.h
+++ b/scene/resources/skeleton_profile.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ot_features_plugin.h */
+/* skeleton_profile.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,75 +28,73 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef OT_FEATURES_PLUGIN_H
-#define OT_FEATURES_PLUGIN_H
+#ifndef SKELETON_PROFILE_H
+#define SKELETON_PROFILE_H
-#include "editor/editor_plugin.h"
-#include "editor/editor_properties.h"
+#include "texture.h"
-/*************************************************************************/
-
-class OpenTypeFeaturesEditor : public EditorProperty {
- GDCLASS(OpenTypeFeaturesEditor, EditorProperty);
- EditorSpinSlider *spin = nullptr;
- bool setting = true;
- void _value_changed(double p_val);
- Button *button = nullptr;
-
- void _remove_feature();
+class SkeletonProfile : public Resource {
+ GDCLASS(SkeletonProfile, Resource);
protected:
- void _notification(int p_what);
+ // Note: SkeletonProfileHumanoid which extends SkeletonProfile exists to unify standard bone names.
+ // That is what is_read_only is for, so don't make it public.
+ bool is_read_only = false;
+
+ struct SkeletonProfileGroup {
+ StringName group_name;
+ Ref<Texture2D> texture;
+ };
+
+ struct SkeletonProfileBone {
+ StringName bone_name;
+ Vector2 handle_offset;
+ StringName group;
+ };
+
+ Vector<SkeletonProfileGroup> groups;
+ Vector<SkeletonProfileBone> bones;
+
+ bool _get(const StringName &p_path, Variant &r_ret) const;
+ bool _set(const StringName &p_path, const Variant &p_value);
+ virtual void _validate_property(PropertyInfo &property) const override;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
static void _bind_methods();
public:
- virtual void update_property() override;
- OpenTypeFeaturesEditor();
-};
+ int get_group_size();
+ void set_group_size(int p_size);
-/*************************************************************************/
-
-class OpenTypeFeaturesAdd : public Button {
- GDCLASS(OpenTypeFeaturesAdd, Button);
+ StringName get_group_name(int p_group_idx) const;
+ void set_group_name(int p_group_idx, const StringName p_group_name);
- Object *edited_object = nullptr;
- PopupMenu *menu = nullptr;
- PopupMenu *menu_ss = nullptr;
- PopupMenu *menu_cv = nullptr;
- PopupMenu *menu_cu = nullptr;
+ Ref<Texture2D> get_texture(int p_group_idx) const;
+ void set_texture(int p_group_idx, const Ref<Texture2D> &p_texture);
- void _add_feature(int p_option);
- void _features_menu();
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
+ int get_bone_size();
+ void set_bone_size(int p_size);
-public:
- void setup(Object *p_object);
+ StringName get_bone_name(int p_bone_idx) const;
+ void set_bone_name(int p_bone_idx, const StringName p_bone_name);
- OpenTypeFeaturesAdd();
-};
+ Vector2 get_handle_offset(int p_bone_idx) const;
+ void set_handle_offset(int p_bone_idx, const Vector2 p_handle_offset);
-/*************************************************************************/
+ StringName get_group(int p_bone_idx) const;
+ void set_group(int p_bone_idx, const StringName p_group);
-class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin {
- GDCLASS(EditorInspectorPluginOpenTypeFeatures, EditorInspectorPlugin);
+ bool has_bone(StringName p_bone_name);
-public:
- virtual bool can_handle(Object *p_object) override;
- virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override;
+ SkeletonProfile();
+ ~SkeletonProfile();
};
-/*************************************************************************/
-
-class OpenTypeFeaturesEditorPlugin : public EditorPlugin {
- GDCLASS(OpenTypeFeaturesEditorPlugin, EditorPlugin);
+class SkeletonProfileHumanoid : public SkeletonProfile {
+ GDCLASS(SkeletonProfileHumanoid, SkeletonProfile);
public:
- OpenTypeFeaturesEditorPlugin();
-
- virtual String get_name() const override { return "OpenTypeFeatures"; }
+ SkeletonProfileHumanoid();
+ ~SkeletonProfileHumanoid();
};
-#endif // OT_FEATURES_PLUGIN_H
+#endif // SKELETON_PROFILE_H
diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp
index 96a47c37c4..0404e1f79b 100644
--- a/scene/resources/text_file.cpp
+++ b/scene/resources/text_file.cpp
@@ -64,7 +64,7 @@ Error TextFile::load_text(const String &p_path) {
w[len] = 0;
String s;
- ERR_FAIL_COND_V_MSG(s.parse_utf8((const char *)w), ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
+ ERR_FAIL_COND_V_MSG(s.parse_utf8((const char *)w) != OK, ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode.");
text = s;
path = p_path;
return OK;
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index d6e7ca3478..f32b7feb4b 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -55,7 +55,7 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextLine::set_bidi_override);
- ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_string", "text", "font", "font_size", "language", "meta"), &TextLine::add_string, DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextLine::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
@@ -149,8 +149,6 @@ RID TextLine::get_rid() const {
void TextLine::clear() {
TS->shaped_text_clear(rid);
- spacing_top = 0;
- spacing_bottom = 0;
}
void TextLine::set_preserve_invalid(bool p_enabled) {
@@ -194,11 +192,12 @@ void TextLine::set_bidi_override(const Array &p_override) {
dirty = true;
}
-bool TextLine::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
- ERR_FAIL_COND_V(p_fonts.is_null(), false);
- bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language, p_meta);
- spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
- spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
+bool TextLine::add_string(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language, const Variant &p_meta) {
+ ERR_FAIL_COND_V(p_font.is_null(), false);
+ bool res = TS->shaped_text_add_string(rid, p_text, p_font->get_rids(), p_font_size, p_font->get_opentype_features(), p_language, p_meta);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(rid, TextServer::SpacingType(i), p_font->get_spacing(TextServer::SpacingType(i)));
+ }
dirty = true;
return res;
}
@@ -278,20 +277,20 @@ float TextLine::get_width() const {
Size2 TextLine::get_size() const {
const_cast<TextLine *>(this)->_shape();
if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y + spacing_top + spacing_bottom);
+ return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y);
} else {
- return Size2(TS->shaped_text_get_size(rid).x + spacing_top + spacing_bottom, TS->shaped_text_get_size(rid).y);
+ return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y);
}
}
float TextLine::get_line_ascent() const {
const_cast<TextLine *>(this)->_shape();
- return TS->shaped_text_get_ascent(rid) + spacing_top;
+ return TS->shaped_text_get_ascent(rid);
}
float TextLine::get_line_descent() const {
const_cast<TextLine *>(this)->_shape();
- return TS->shaped_text_get_descent(rid) + spacing_bottom;
+ return TS->shaped_text_get_descent(rid);
}
float TextLine::get_line_width() const {
@@ -347,10 +346,10 @@ void TextLine::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_color) co
float clip_l;
if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y += TS->shaped_text_get_ascent(rid) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(rid);
clip_l = MAX(0, p_pos.x - ofs.x);
} else {
- ofs.x += TS->shaped_text_get_ascent(rid) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(rid);
clip_l = MAX(0, p_pos.y - ofs.y);
}
return TS->shaped_text_draw(rid, p_canvas, ofs, clip_l, clip_l + width, p_color);
@@ -394,10 +393,10 @@ void TextLine::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outline_si
float clip_l;
if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y += TS->shaped_text_get_ascent(rid) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(rid);
clip_l = MAX(0, p_pos.x - ofs.x);
} else {
- ofs.x += TS->shaped_text_get_ascent(rid) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(rid);
clip_l = MAX(0, p_pos.y - ofs.y);
}
return TS->shaped_text_draw_outline(rid, p_canvas, ofs, clip_l, clip_l + width, p_outline_size, p_color);
@@ -409,11 +408,14 @@ int TextLine::hit_test(float p_coords) const {
return TS->shaped_text_hit_test_position(rid, p_coords);
}
-TextLine::TextLine(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
+TextLine::TextLine(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language, TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
rid = TS->create_shaped_text(p_direction, p_orientation);
- spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
- spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
- TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
+ if (p_font.is_valid()) {
+ TS->shaped_text_add_string(rid, p_text, p_font->get_rids(), p_font_size, p_font->get_opentype_features(), p_language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(rid, TextServer::SpacingType(i), p_font->get_spacing(TextServer::SpacingType(i)));
+ }
+ }
}
TextLine::TextLine() {
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index 784ee8ef26..2d1548d079 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -41,8 +41,6 @@ class TextLine : public RefCounted {
private:
RID rid;
- int spacing_top = 0;
- int spacing_bottom = 0;
bool dirty = true;
@@ -77,7 +75,7 @@ public:
void set_preserve_control(bool p_enabled);
bool get_preserve_control() const;
- bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant());
+ bool add_string(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", const Variant &p_meta = Variant());
bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1);
bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER);
@@ -111,7 +109,7 @@ public:
int hit_test(float p_coords) const;
- TextLine(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
+ TextLine(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
TextLine();
~TextLine();
};
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 874992ea3d..c8b9e895fc 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -60,10 +60,10 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextParagraph::set_bidi_override);
- ClassDB::bind_method(D_METHOD("set_dropcap", "text", "fonts", "size", "dropcap_margins", "opentype_features", "language"), &TextParagraph::set_dropcap, DEFVAL(Rect2()), DEFVAL(Dictionary()), DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("set_dropcap", "text", "font", "font_size", "dropcap_margins", "language"), &TextParagraph::set_dropcap, DEFVAL(Rect2()), DEFVAL(""));
ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap);
- ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextParagraph::add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_string", "text", "font", "font_size", "language", "meta"), &TextParagraph::add_string, DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextParagraph::add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextParagraph::resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
@@ -113,9 +113,6 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_underline_position", "line"), &TextParagraph::get_line_underline_position);
ClassDB::bind_method(D_METHOD("get_line_underline_thickness", "line"), &TextParagraph::get_line_underline_thickness);
- ClassDB::bind_method(D_METHOD("get_spacing_top"), &TextParagraph::get_spacing_top);
- ClassDB::bind_method(D_METHOD("get_spacing_bottom"), &TextParagraph::get_spacing_bottom);
-
ClassDB::bind_method(D_METHOD("get_dropcap_size"), &TextParagraph::get_dropcap_size);
ClassDB::bind_method(D_METHOD("get_dropcap_lines"), &TextParagraph::get_dropcap_lines);
@@ -266,8 +263,6 @@ RID TextParagraph::get_dropcap_rid() const {
void TextParagraph::clear() {
_THREAD_SAFE_METHOD_
- spacing_top = 0;
- spacing_bottom = 0;
for (int i = 0; i < (int)lines_rid.size(); i++) {
TS->free_rid(lines_rid[i]);
}
@@ -347,44 +342,37 @@ TextServer::Orientation TextParagraph::get_orientation() const {
return TS->shaped_text_get_orientation(rid);
}
-bool TextParagraph::set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins, const Dictionary &p_opentype_features, const String &p_language) {
+bool TextParagraph::set_dropcap(const String &p_text, const Ref<Font> &p_font, int p_font_size, const Rect2 &p_dropcap_margins, const String &p_language) {
_THREAD_SAFE_METHOD_
-
- ERR_FAIL_COND_V(p_fonts.is_null(), false);
+ ERR_FAIL_COND_V(p_font.is_null(), false);
TS->shaped_text_clear(dropcap_rid);
dropcap_margins = p_dropcap_margins;
- bool res = TS->shaped_text_add_string(dropcap_rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
+ bool res = TS->shaped_text_add_string(dropcap_rid, p_text, p_font->get_rids(), p_font_size, p_font->get_opentype_features(), p_language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(dropcap_rid, TextServer::SpacingType(i), p_font->get_spacing(TextServer::SpacingType(i)));
+ }
lines_dirty = true;
return res;
}
void TextParagraph::clear_dropcap() {
_THREAD_SAFE_METHOD_
-
dropcap_margins = Rect2();
TS->shaped_text_clear(dropcap_rid);
lines_dirty = true;
}
-bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
+bool TextParagraph::add_string(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language, const Variant &p_meta) {
_THREAD_SAFE_METHOD_
-
- ERR_FAIL_COND_V(p_fonts.is_null(), false);
- bool res = TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language, p_meta);
- spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
- spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
+ ERR_FAIL_COND_V(p_font.is_null(), false);
+ bool res = TS->shaped_text_add_string(rid, p_text, p_font->get_rids(), p_font_size, p_font->get_opentype_features(), p_language, p_meta);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(rid, TextServer::SpacingType(i), p_font->get_spacing(TextServer::SpacingType(i)));
+ }
lines_dirty = true;
return res;
}
-int TextParagraph::get_spacing_top() const {
- return spacing_top;
-}
-
-int TextParagraph::get_spacing_bottom() const {
- return spacing_bottom;
-}
-
void TextParagraph::set_bidi_override(const Array &p_override) {
_THREAD_SAFE_METHOD_
@@ -476,9 +464,9 @@ Size2 TextParagraph::get_non_wrapped_size() const {
const_cast<TextParagraph *>(this)->_shape_lines();
if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y + spacing_top + spacing_bottom);
+ return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y);
} else {
- return Size2(TS->shaped_text_get_size(rid).x + spacing_top + spacing_bottom, TS->shaped_text_get_size(rid).y);
+ return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y);
}
}
@@ -492,9 +480,9 @@ Size2 TextParagraph::get_size() const {
Size2 lsize = TS->shaped_text_get_size(lines_rid[i]);
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
size.x = MAX(size.x, lsize.x);
- size.y += lsize.y + spacing_top + spacing_bottom;
+ size.y += lsize.y;
} else {
- size.x += lsize.x + spacing_top + spacing_bottom;
+ size.x += lsize.x;
size.y = MAX(size.y, lsize.y);
}
}
@@ -538,9 +526,9 @@ Rect2 TextParagraph::get_line_object_rect(int p_line, Variant p_key) const {
for (int i = 0; i < p_line; i++) {
Size2 lsize = TS->shaped_text_get_size(lines_rid[i]);
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
- xrect.position.y += lsize.y + spacing_top + spacing_bottom;
+ xrect.position.y += lsize.y;
} else {
- xrect.position.x += lsize.x + spacing_top + spacing_bottom;
+ xrect.position.x += lsize.x;
}
}
return xrect;
@@ -552,9 +540,9 @@ Size2 TextParagraph::get_line_size(int p_line) const {
const_cast<TextParagraph *>(this)->_shape_lines();
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)lines_rid.size(), Size2());
if (TS->shaped_text_get_orientation(lines_rid[p_line]) == TextServer::ORIENTATION_HORIZONTAL) {
- return Size2(TS->shaped_text_get_size(lines_rid[p_line]).x, TS->shaped_text_get_size(lines_rid[p_line]).y + spacing_top + spacing_bottom);
+ return Size2(TS->shaped_text_get_size(lines_rid[p_line]).x, TS->shaped_text_get_size(lines_rid[p_line]).y);
} else {
- return Size2(TS->shaped_text_get_size(lines_rid[p_line]).x + spacing_top + spacing_bottom, TS->shaped_text_get_size(lines_rid[p_line]).y);
+ return Size2(TS->shaped_text_get_size(lines_rid[p_line]).x, TS->shaped_text_get_size(lines_rid[p_line]).y);
}
}
@@ -571,7 +559,7 @@ float TextParagraph::get_line_ascent(int p_line) const {
const_cast<TextParagraph *>(this)->_shape_lines();
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)lines_rid.size(), 0.f);
- return TS->shaped_text_get_ascent(lines_rid[p_line]) + spacing_top;
+ return TS->shaped_text_get_ascent(lines_rid[p_line]);
}
float TextParagraph::get_line_descent(int p_line) const {
@@ -579,7 +567,7 @@ float TextParagraph::get_line_descent(int p_line) const {
const_cast<TextParagraph *>(this)->_shape_lines();
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)lines_rid.size(), 0.f);
- return TS->shaped_text_get_descent(lines_rid[p_line]) + spacing_bottom;
+ return TS->shaped_text_get_descent(lines_rid[p_line]);
}
float TextParagraph::get_line_width(int p_line) const {
@@ -647,7 +635,7 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
float l_width = width;
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
ofs.x = p_pos.x;
- ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[i]);
if (i <= dropcap_lines) {
if (TS->shaped_text_get_inferred_direction(dropcap_rid) == TextServer::DIRECTION_LTR) {
ofs.x -= h_offset;
@@ -656,7 +644,7 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
}
} else {
ofs.y = p_pos.y;
- ofs.x += TS->shaped_text_get_ascent(lines_rid[i]) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(lines_rid[i]);
if (i <= dropcap_lines) {
if (TS->shaped_text_get_inferred_direction(dropcap_rid) == TextServer::DIRECTION_LTR) {
ofs.x -= h_offset;
@@ -711,10 +699,10 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
TS->shaped_text_draw(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_color);
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
ofs.x = p_pos.x;
- ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + spacing_bottom;
+ ofs.y += TS->shaped_text_get_descent(lines_rid[i]);
} else {
ofs.y = p_pos.y;
- ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + spacing_bottom;
+ ofs.x += TS->shaped_text_get_descent(lines_rid[i]);
}
}
}
@@ -749,7 +737,7 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli
float l_width = width;
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
ofs.x = p_pos.x;
- ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[i]);
if (i <= dropcap_lines) {
if (TS->shaped_text_get_inferred_direction(dropcap_rid) == TextServer::DIRECTION_LTR) {
ofs.x -= h_offset;
@@ -758,7 +746,7 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli
}
} else {
ofs.y = p_pos.y;
- ofs.x += TS->shaped_text_get_ascent(lines_rid[i]) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(lines_rid[i]);
if (i <= dropcap_lines) {
if (TS->shaped_text_get_inferred_direction(dropcap_rid) == TextServer::DIRECTION_LTR) {
ofs.x -= h_offset;
@@ -813,10 +801,10 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli
TS->shaped_text_draw_outline(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_outline_size, p_color);
if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
ofs.x = p_pos.x;
- ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + spacing_bottom;
+ ofs.y += TS->shaped_text_get_descent(lines_rid[i]);
} else {
ofs.y = p_pos.y;
- ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + spacing_bottom;
+ ofs.x += TS->shaped_text_get_descent(lines_rid[i]);
}
}
}
@@ -840,12 +828,12 @@ int TextParagraph::hit_test(const Point2 &p_coords) const {
if ((p_coords.y >= ofs.y) && (p_coords.y <= ofs.y + TS->shaped_text_get_size(lines_rid[i]).y)) {
return TS->shaped_text_hit_test_position(lines_rid[i], p_coords.x);
}
- ofs.y += TS->shaped_text_get_size(lines_rid[i]).y + spacing_bottom + spacing_top;
+ ofs.y += TS->shaped_text_get_size(lines_rid[i]).y;
} else {
if ((p_coords.x >= ofs.x) && (p_coords.x <= ofs.x + TS->shaped_text_get_size(lines_rid[i]).x)) {
return TS->shaped_text_hit_test_position(lines_rid[i], p_coords.y);
}
- ofs.y += TS->shaped_text_get_size(lines_rid[i]).x + spacing_bottom + spacing_top;
+ ofs.y += TS->shaped_text_get_size(lines_rid[i]).x;
}
}
return TS->shaped_text_get_range(rid).y;
@@ -908,9 +896,9 @@ void TextParagraph::draw_line(RID p_canvas, const Vector2 &p_pos, int p_line, co
Vector2 ofs = p_pos;
if (TS->shaped_text_get_orientation(lines_rid[p_line]) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y += TS->shaped_text_get_ascent(lines_rid[p_line]) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[p_line]);
} else {
- ofs.x += TS->shaped_text_get_ascent(lines_rid[p_line]) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(lines_rid[p_line]);
}
return TS->shaped_text_draw(lines_rid[p_line], p_canvas, ofs, -1, -1, p_color);
}
@@ -923,18 +911,21 @@ void TextParagraph::draw_line_outline(RID p_canvas, const Vector2 &p_pos, int p_
Vector2 ofs = p_pos;
if (TS->shaped_text_get_orientation(lines_rid[p_line]) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.y += TS->shaped_text_get_ascent(lines_rid[p_line]) + spacing_top;
+ ofs.y += TS->shaped_text_get_ascent(lines_rid[p_line]);
} else {
- ofs.x += TS->shaped_text_get_ascent(lines_rid[p_line]) + spacing_top;
+ ofs.x += TS->shaped_text_get_ascent(lines_rid[p_line]);
}
return TS->shaped_text_draw_outline(lines_rid[p_line], p_canvas, ofs, -1, -1, p_outline_size, p_color);
}
-TextParagraph::TextParagraph(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language, float p_width, TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
+TextParagraph::TextParagraph(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language, float p_width, TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
rid = TS->create_shaped_text(p_direction, p_orientation);
- TS->shaped_text_add_string(rid, p_text, p_fonts->get_rids(), p_size, p_opentype_features, p_language);
- spacing_top = p_fonts->get_spacing(TextServer::SPACING_TOP);
- spacing_bottom = p_fonts->get_spacing(TextServer::SPACING_BOTTOM);
+ if (p_font.is_valid()) {
+ TS->shaped_text_add_string(rid, p_text, p_font->get_rids(), p_font_size, p_font->get_opentype_features(), p_language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(rid, TextServer::SpacingType(i), p_font->get_spacing(TextServer::SpacingType(i)));
+ }
+ }
width = p_width;
}
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index bdcc2b5701..f161cb5b8c 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -48,8 +48,6 @@ private:
RID rid;
LocalVector<RID> lines_rid;
- int spacing_top = 0;
- int spacing_bottom = 0;
bool lines_dirty = true;
@@ -92,10 +90,10 @@ public:
void set_custom_punctuation(const String &p_punct);
String get_custom_punctuation() const;
- bool set_dropcap(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
+ bool set_dropcap(const String &p_text, const Ref<Font> &p_font, int p_font_size, const Rect2 &p_dropcap_margins = Rect2(), const String &p_language = "");
void clear_dropcap();
- bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant());
+ bool add_string(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", const Variant &p_meta = Variant());
bool add_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int p_length = 1);
bool resize_object(Variant p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER);
@@ -151,7 +149,7 @@ public:
Mutex &get_mutex() const { return _thread_safe_; };
- TextParagraph(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
+ TextParagraph(const String &p_text, const Ref<Font> &p_font, int p_font_size, const String &p_language = "", float p_width = -1.f, TextServer::Direction p_direction = TextServer::DIRECTION_AUTO, TextServer::Orientation p_orientation = TextServer::ORIENTATION_HORIZONTAL);
TextParagraph();
~TextParagraph();
};
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index f31a71eada..8c175e9ced 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -139,7 +139,7 @@ void ImageTexture::reload_from_file() {
img.instantiate();
if (ImageLoader::load_image(path, img) == OK) {
- create_from_image(img);
+ set_image(img);
} else {
Resource::reload_from_file();
notify_property_list_changed();
@@ -149,7 +149,7 @@ void ImageTexture::reload_from_file() {
bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) {
if (p_name == "image") {
- create_from_image(p_value);
+ set_image(p_value);
return true;
}
return false;
@@ -167,7 +167,16 @@ void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, PNAME("image"), PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT));
}
-void ImageTexture::create_from_image(const Ref<Image> &p_image) {
+Ref<ImageTexture> ImageTexture::create_from_image(const Ref<Image> &p_image) {
+ ERR_FAIL_COND_V_MSG(p_image.is_null() || p_image->is_empty(), Ref<ImageTexture>(), "Invalid image");
+
+ Ref<ImageTexture> image_texture;
+ image_texture.instantiate();
+ image_texture->set_image(p_image);
+ return image_texture;
+}
+
+void ImageTexture::set_image(const Ref<Image> &p_image) {
ERR_FAIL_COND_MSG(p_image.is_null() || p_image->is_empty(), "Invalid image");
w = p_image->get_width();
h = p_image->get_height();
@@ -311,7 +320,7 @@ void ImageTexture::set_path(const String &p_path, bool p_take_over) {
}
void ImageTexture::_bind_methods() {
- ClassDB::bind_method(D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image);
+ ClassDB::bind_static_method("ImageTexture", D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image);
ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format);
ClassDB::bind_method(D_METHOD("update", "image"), &ImageTexture::update);
@@ -3016,12 +3025,12 @@ Error ImageTextureLayered::create_from_images(Vector<Ref<Image>> p_images) {
}
void ImageTextureLayered::update_layer(const Ref<Image> &p_image, int p_layer) {
- ERR_FAIL_COND(texture.is_valid());
- ERR_FAIL_COND(p_image.is_null());
- ERR_FAIL_COND(p_image->get_format() != format);
- ERR_FAIL_COND(p_image->get_width() != width || p_image->get_height() != height);
- ERR_FAIL_INDEX(p_layer, layers);
- ERR_FAIL_COND(p_image->has_mipmaps() != mipmaps);
+ ERR_FAIL_COND_MSG(texture.is_null(), "Texture is not initialized.");
+ ERR_FAIL_COND_MSG(p_image.is_null(), "Invalid image.");
+ ERR_FAIL_COND_MSG(p_image->get_format() != format, "Image format must match texture's image format.");
+ ERR_FAIL_COND_MSG(p_image->get_width() != width || p_image->get_height() != height, "Image size must match texture's image size.");
+ ERR_FAIL_COND_MSG(p_image->has_mipmaps() != mipmaps, "Image mipmap configuration must match texture's image mipmap configuration.");
+ ERR_FAIL_INDEX_MSG(p_layer, layers, "Layer index is out of bounds.");
RS::get_singleton()->texture_2d_update(texture, p_image, p_layer);
}
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 317756e313..5973643034 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -110,7 +110,8 @@ protected:
static void _bind_methods();
public:
- void create_from_image(const Ref<Image> &p_image);
+ void set_image(const Ref<Image> &p_image);
+ static Ref<ImageTexture> create_from_image(const Ref<Image> &p_image);
Image::Format get_format() const;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 13b671e562..05483db1e4 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -1809,11 +1809,8 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
image->create(1, 1, false, Image::FORMAT_RGBA8);
image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain));
}
- Ref<ImageTexture> icon;
- icon.instantiate();
- icon->create_from_image(image);
+ Ref<ImageTexture> icon = ImageTexture::create_from_image(image);
icon->set_size_override(p_size);
-
output.write[terrain_set].write[terrain] = icon;
}
}
@@ -4594,7 +4591,7 @@ void TileSetAtlasSource::_update_padded_texture() {
if (!padded_texture.is_valid()) {
padded_texture.instantiate();
}
- padded_texture->create_from_image(image);
+ padded_texture->set_image(image);
emit_changed();
}
@@ -4924,6 +4921,10 @@ void TileData::move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) {
void TileData::remove_terrain(int p_terrain_set, int p_index) {
if (terrain_set == p_terrain_set) {
+ if (terrain == p_index) {
+ terrain = -1;
+ }
+
for (int i = 0; i < 16; i++) {
if (terrain_peering_bits[i] == p_index) {
terrain_peering_bits[i] = -1;
diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp
index 54df935168..bdfbb59fa6 100644
--- a/scene/resources/visual_shader_particle_nodes.cpp
+++ b/scene/resources/visual_shader_particle_nodes.cpp
@@ -470,7 +470,7 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector2>
image->set_pixel(i, 0, Color(v.x, v.y, 0));
}
if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
- r_texture->create_from_image(image);
+ r_texture->set_image(image);
} else {
r_texture->update(image);
}
@@ -491,7 +491,7 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Vector3>
image->set_pixel(i, 0, Color(v.x, v.y, v.z));
}
if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
- r_texture->create_from_image(image);
+ r_texture->set_image(image);
} else {
r_texture->update(image);
}
@@ -511,7 +511,7 @@ void VisualShaderNodeParticleMeshEmitter::_update_texture(const Vector<Color> &p
image->set_pixel(i, 0, p_array[i]);
}
if (r_texture->get_width() != p_array.size() || p_array.size() == 0) {
- r_texture->create_from_image(image);
+ r_texture->set_image(image);
} else {
r_texture->update(image);
}
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index a84ee773b4..fb6dcd3d57 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -31,7 +31,6 @@
#include "world_3d.h"
#include "core/config/project_settings.h"
-#include "core/math/octree.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/visible_on_screen_notifier_3d.h"
#include "scene/scene_string_names.h"
diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub
index 06d1d28b08..cf26ca029d 100644
--- a/servers/rendering/SCsub
+++ b/servers/rendering/SCsub
@@ -4,5 +4,6 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
+SConscript("dummy/SCsub")
SConscript("renderer_rd/SCsub")
SConscript("storage/SCsub")
diff --git a/servers/rendering/dummy/SCsub b/servers/rendering/dummy/SCsub
new file mode 100644
index 0000000000..aa688af6cd
--- /dev/null
+++ b/servers/rendering/dummy/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
+
+SConscript("storage/SCsub")
diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h
new file mode 100644
index 0000000000..8a2be90507
--- /dev/null
+++ b/servers/rendering/dummy/environment/fog.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FOG_DUMMY_H
+#define FOG_DUMMY_H
+
+#include "servers/rendering/environment/renderer_fog.h"
+
+namespace RendererDummy {
+
+class Fog : public RendererFog {
+public:
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() override { return RID(); }
+ virtual void fog_volume_initialize(RID p_rid) override {}
+ virtual void fog_free(RID p_rid) override {}
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+};
+
+} // namespace RendererDummy
+
+#endif // !FOG_DUMMY_H
diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h
index 374f0c8923..9c7647c2de 100644
--- a/servers/rendering/dummy/environment/gi.h
+++ b/servers/rendering/dummy/environment/gi.h
@@ -74,9 +74,6 @@ public:
virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {}
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; }
-
virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override { return 0; }
};
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 9c2bd45cce..d867114384 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -34,15 +34,16 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "scene/resources/mesh.h"
+#include "servers/rendering/dummy/environment/fog.h"
#include "servers/rendering/dummy/environment/gi.h"
#include "servers/rendering/dummy/rasterizer_canvas_dummy.h"
#include "servers/rendering/dummy/rasterizer_scene_dummy.h"
-#include "servers/rendering/dummy/rasterizer_storage_dummy.h"
#include "servers/rendering/dummy/storage/light_storage.h"
#include "servers/rendering/dummy/storage/material_storage.h"
#include "servers/rendering/dummy/storage/mesh_storage.h"
#include "servers/rendering/dummy/storage/particles_storage.h"
#include "servers/rendering/dummy/storage/texture_storage.h"
+#include "servers/rendering/dummy/storage/utilities.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
@@ -53,23 +54,25 @@ private:
protected:
RasterizerCanvasDummy canvas;
+ RendererDummy::Utilities utilities;
RendererDummy::LightStorage light_storage;
RendererDummy::MaterialStorage material_storage;
RendererDummy::MeshStorage mesh_storage;
RendererDummy::ParticlesStorage particles_storage;
RendererDummy::TextureStorage texture_storage;
RendererDummy::GI gi;
- RasterizerStorageDummy storage;
+ RendererDummy::Fog fog;
RasterizerSceneDummy scene;
public:
+ RendererUtilities *get_utilities() override { return &utilities; };
RendererLightStorage *get_light_storage() override { return &light_storage; };
RendererMaterialStorage *get_material_storage() override { return &material_storage; };
RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };
RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
RendererGI *get_gi() override { return &gi; };
- RendererStorage *get_storage() override { return &storage; }
+ RendererFog *get_fog() override { return &fog; };
RendererCanvasRender *get_canvas() override { return &canvas; }
RendererSceneRender *get_scene() override { return &scene; }
diff --git a/servers/rendering/dummy/storage/SCsub b/servers/rendering/dummy/storage/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/dummy/storage/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index 8890be8ea9..d4809f81e3 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -32,6 +32,7 @@
#define MATERIAL_STORAGE_DUMMY_H
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
@@ -87,7 +88,7 @@ public:
virtual bool material_is_animated(RID p_material) override { return false; }
virtual bool material_casts_shadows(RID p_material) override { return false; }
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
};
} // namespace RendererDummy
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index dfbd265bba..78b19d721d 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -32,6 +32,7 @@
#define MESH_STORAGE_DUMMY_H
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
@@ -121,7 +122,11 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
- virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {}
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+
+ /* OCCLUDER */
+
+ void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
};
} // namespace RendererDummy
diff --git a/servers/rendering/dummy/storage/texture_storage.cpp b/servers/rendering/dummy/storage/texture_storage.cpp
new file mode 100644
index 0000000000..62e2a306a2
--- /dev/null
+++ b/servers/rendering/dummy/storage/texture_storage.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* texture_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "texture_storage.h"
+
+using namespace RendererDummy;
+
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage::TextureStorage() {
+ singleton = this;
+}
+
+TextureStorage::~TextureStorage() {
+ singleton = nullptr;
+}
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 11d827a6e3..fe10f6489c 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -38,6 +38,8 @@ namespace RendererDummy {
class TextureStorage : public RendererTextureStorage {
private:
+ static TextureStorage *singleton;
+
struct DummyTexture {
Ref<Image> image;
};
@@ -45,11 +47,12 @@ private:
public:
static TextureStorage *get_singleton() {
- // Here we cheat until we can retire RasterizerStorageDummy::free()
-
- return (TextureStorage *)RSG::texture_storage;
+ return singleton;
};
+ TextureStorage();
+ ~TextureStorage();
+
virtual bool can_create_resources_async() const override { return false; }
/* Canvas Texture API */
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/storage/utilities.h
index 7f637d2c42..f090309e88 100644
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ b/servers/rendering/dummy/storage/utilities.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* rasterizer_storage_dummy.h */
+/* utilities.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,79 +28,71 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RASTERIZER_STORAGE_DUMMY_H
-#define RASTERIZER_STORAGE_DUMMY_H
+#ifndef UTILITIES_DUMMY_H
+#define UTILITIES_DUMMY_H
-#include "servers/rendering/renderer_storage.h"
-#include "storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
+#include "texture_storage.h"
-class RasterizerStorageDummy : public RendererStorage {
-public:
- void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
-
- /* OCCLUDER */
+namespace RendererDummy {
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
+class Utilities : public RendererUtilities {
+public:
+ /* INSTANCES */
- /* FOG VOLUMES */
+ virtual RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
+ virtual bool free(RID p_rid) override {
+ if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
+ return true;
+ }
+ return false;
+ }
- RID fog_volume_allocate() override { return RID(); }
- void fog_volume_initialize(RID p_rid) override {}
+ /* DEPENDENCIES */
- void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
- void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
- void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
- AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
- RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
/* VISIBILITY NOTIFIER */
+
virtual RID visibility_notifier_allocate() override { return RID(); }
virtual void visibility_notifier_initialize(RID p_notifier) override {}
+ virtual void visibility_notifier_free(RID p_notifier) override {}
+
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
- /* STORAGE */
+ /* TIMING */
- RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
- bool free(RID p_rid) override {
- if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
- RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
- return true;
- }
- return false;
- }
+ virtual void capture_timestamps_begin() override {}
+ virtual void capture_timestamp(const String &p_name) override {}
+ virtual uint32_t get_captured_timestamps_count() const override { return 0; }
+ virtual uint64_t get_captured_timestamps_frame() const override { return 0; }
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
+ virtual String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
- virtual void update_memory_info() override {}
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
+ /* MISC */
+
+ virtual void update_dirty_resources() override {}
+ virtual void set_debug_generate_wireframes(bool p_generate) override {}
- bool has_os_feature(const String &p_feature) const override {
+ virtual bool has_os_feature(const String &p_feature) const override {
return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
}
- void update_dirty_resources() override {}
-
- void set_debug_generate_wireframes(bool p_generate) override {}
-
- String get_video_adapter_name() const override { return String(); }
- String get_video_adapter_vendor() const override { return String(); }
- RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
- String get_video_adapter_api_version() const override { return String(); }
-
- static RendererStorage *base_singleton;
-
- void capture_timestamps_begin() override {}
- void capture_timestamp(const String &p_name) override {}
- uint32_t get_captured_timestamps_count() const override { return 0; }
- uint64_t get_captured_timestamps_frame() const override { return 0; }
- uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
- uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
- String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
+ virtual void update_memory_info() override {}
- RasterizerStorageDummy() {}
- ~RasterizerStorageDummy() {}
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
+ virtual String get_video_adapter_name() const override { return String(); }
+ virtual String get_video_adapter_vendor() const override { return String(); }
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
+ virtual String get_video_adapter_api_version() const override { return String(); }
};
-#endif // !RASTERIZER_STORAGE_DUMMY_H
+} // namespace RendererDummy
+
+#endif // !UTILITIES_DUMMY_H
diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h
new file mode 100644
index 0000000000..ac50da0fc0
--- /dev/null
+++ b/servers/rendering/environment/renderer_fog.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* renderer_fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RENDERER_FOG_H
+#define RENDERER_FOG_H
+
+#include "servers/rendering_server.h"
+
+class RendererFog {
+public:
+ virtual ~RendererFog() {}
+
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() = 0;
+ virtual void fog_volume_initialize(RID p_rid) = 0;
+ virtual void fog_free(RID p_rid) = 0;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
+};
+
+#endif // !RENDERER_FOG_H
diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h
index c4f63b7b6b..4f93bb8675 100644
--- a/servers/rendering/environment/renderer_gi.h
+++ b/servers/rendering/environment/renderer_gi.h
@@ -31,7 +31,6 @@
#ifndef RENDERER_GI_H
#define RENDERER_GI_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
class RendererGI {
@@ -76,9 +75,6 @@ public:
virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0;
-
virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0;
};
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index bc1e8eb348..dea68ac61c 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -76,10 +76,11 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
}
}
-void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index) {
+void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index, int p_z) {
int child_item_count = p_canvas_item->child_items.size();
RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
+ int abs_z = 0;
if (child_items[i]->visible) {
if (r_items) {
r_items[r_index] = child_items[i];
@@ -87,12 +88,20 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_index = r_index;
+ child_items[i]->ysort_parent_abs_z_index = p_z;
+
+ // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items.
+ if (child_items[i]->z_relative) {
+ abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
+ } else {
+ abs_z = child_items[i]->z_index;
+ }
}
r_index++;
if (child_items[i]->sort_y) {
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index);
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index, abs_z);
}
}
}
@@ -277,6 +286,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
ci->final_clip_owner = p_canvas_clip;
}
+ int parent_z = p_z;
if (ci->z_relative) {
p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
} else {
@@ -287,22 +297,23 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (allow_y_sort) {
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count, p_z);
}
child_item_count = ci->ysort_children_count + 1;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+ ci->ysort_parent_abs_z_index = parent_z;
child_items[0] = ci;
int i = 1;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i, p_z);
ci->ysort_xform = ci->xform.affine_inverse();
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
for (i = 0; i < child_item_count; i++) {
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
+ _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 963cca7630..48d0598c9f 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -53,6 +53,7 @@ public:
Transform2D ysort_xform;
Vector2 ysort_pos;
int ysort_index;
+ int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting.
Vector<Item *> child_items;
@@ -84,6 +85,7 @@ public:
ysort_xform = Transform2D();
ysort_pos = Vector2();
ysort_index = 0;
+ ysort_parent_abs_z_index = 0;
}
};
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 163a24247e..f93fdd500a 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -128,3 +128,9 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
rect_dirty = false;
return rect;
}
+
+RendererCanvasRender::Item::CommandMesh::~CommandMesh() {
+ if (mesh_instance.is_valid()) {
+ RSG::mesh_storage->mesh_free(mesh_instance);
+ }
+}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1724a99b20..52b2f82089 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -31,7 +31,7 @@
#ifndef RENDERINGSERVERCANVASRENDER_H
#define RENDERINGSERVERCANVASRENDER_H
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
class RendererCanvasRender {
public:
@@ -257,11 +257,7 @@ public:
RID texture;
CommandMesh() { type = TYPE_MESH; }
- ~CommandMesh() {
- if (mesh_instance.is_valid()) {
- RendererStorage::base_singleton->free(mesh_instance);
- }
- }
+ ~CommandMesh();
};
struct CommandMultiMesh : public Command {
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index f58bc851ef..a67eb25736 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -31,15 +31,16 @@
#ifndef RENDERING_SERVER_COMPOSITOR_H
#define RENDERING_SERVER_COMPOSITOR_H
+#include "servers/rendering/environment/renderer_fog.h"
#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "servers/rendering_server.h"
class RendererSceneRender;
@@ -77,13 +78,14 @@ protected:
public:
static RendererCompositor *create();
+ virtual RendererUtilities *get_utilities() = 0;
virtual RendererLightStorage *get_light_storage() = 0;
virtual RendererMaterialStorage *get_material_storage() = 0;
virtual RendererMeshStorage *get_mesh_storage() = 0;
virtual RendererParticlesStorage *get_particles_storage() = 0;
virtual RendererTextureStorage *get_texture_storage() = 0;
virtual RendererGI *get_gi() = 0;
- virtual RendererStorage *get_storage() = 0;
+ virtual RendererFog *get_fog() = 0;
virtual RendererCanvasRender *get_canvas() = 0;
virtual RendererSceneRender *get_scene() = 0;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 0b36fe3964..228933d618 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -413,7 +413,7 @@ void ClusterBuilderRD::bake_cluster() {
StateUniform state;
- RendererStorageRD::store_camera(adjusted_projection, state.projection);
+ RendererRD::MaterialStorage::store_camera(adjusted_projection, state.projection);
state.inv_z_far = 1.0 / z_far;
state.screen_to_clusters_shift = get_shift_from_power_of_2(cluster_size);
state.screen_to_clusters_shift -= divisor; //screen is smaller, shift one less
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index e82193ea6a..74ca530ff6 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -31,10 +31,10 @@
#ifndef CLUSTER_BUILDER_RD_H
#define CLUSTER_BUILDER_RD_H
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/cluster_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cluster_render.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cluster_store.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
class ClusterBuilderSharedDataRD {
friend class ClusterBuilderRD;
@@ -261,7 +261,7 @@ public:
e.type = ELEMENT_TYPE_OMNI_LIGHT;
e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT];
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
@@ -309,7 +309,7 @@ public:
e.type = ELEMENT_TYPE_SPOT_LIGHT;
e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]++;
}
@@ -356,7 +356,7 @@ public:
e.type = (p_box_type == BOX_TYPE_DECAL) ? ELEMENT_TYPE_DECAL : ELEMENT_TYPE_REFLECTION_PROBE;
e.original_index = cluster_count_by_type[e.type];
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[e.type]++;
render_element_count++;
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
new file mode 100644
index 0000000000..2a6c96480e
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* fog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "fog.h"
+
+using namespace RendererRD;
+
+Fog *Fog::singleton = nullptr;
+
+Fog::Fog() {
+ singleton = this;
+}
+
+Fog::~Fog() {
+ singleton = nullptr;
+}
+
+/* FOG VOLUMES */
+
+RID Fog::fog_volume_allocate() {
+ return fog_volume_owner.allocate_rid();
+}
+
+void Fog::fog_volume_initialize(RID p_rid) {
+ fog_volume_owner.initialize_rid(p_rid, FogVolume());
+}
+
+void Fog::fog_free(RID p_rid) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
+ fog_volume->dependency.deleted_notify(p_rid);
+ fog_volume_owner.free(p_rid);
+}
+
+void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ if (p_shape == fog_volume->shape) {
+ return;
+ }
+
+ fog_volume->shape = p_shape;
+ fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ fog_volume->extents = p_extents;
+ fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+ fog_volume->material = p_material;
+}
+
+RID Fog::fog_volume_get_material(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RID());
+
+ return fog_volume->material;
+}
+
+RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
+
+ return fog_volume->shape;
+}
+
+AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, AABB());
+
+ switch (fog_volume->shape) {
+ case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
+ case RS::FOG_VOLUME_SHAPE_CONE:
+ case RS::FOG_VOLUME_SHAPE_CYLINDER:
+ case RS::FOG_VOLUME_SHAPE_BOX: {
+ AABB aabb;
+ aabb.position = -fog_volume->extents;
+ aabb.size = fog_volume->extents * 2;
+ return aabb;
+ }
+ default: {
+ // Need some size otherwise will get culled
+ return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ }
+ }
+
+ return AABB();
+}
+
+Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const {
+ const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, Vector3());
+ return fog_volume->extents;
+}
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
new file mode 100644
index 0000000000..55a01c3616
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef FOG_RD_H
+#define FOG_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/environment/renderer_fog.h"
+#include "servers/rendering/storage/utilities.h"
+
+namespace RendererRD {
+
+class Fog : public RendererFog {
+public:
+ struct FogVolume {
+ RID material;
+ Vector3 extents = Vector3(1, 1, 1);
+
+ RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
+
+ Dependency dependency;
+ };
+
+private:
+ static Fog *singleton;
+
+ mutable RID_Owner<FogVolume, true> fog_volume_owner;
+
+public:
+ static Fog *get_singleton() { return singleton; }
+
+ Fog();
+ ~Fog();
+
+ /* FOG VOLUMES */
+
+ FogVolume *get_fog_volume(RID p_rid) { return fog_volume_owner.get_or_null(p_rid); };
+ bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
+
+ virtual RID fog_volume_allocate() override;
+ virtual void fog_volume_initialize(RID p_rid) override;
+ virtual void fog_free(RID p_rid) override;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
+ RID fog_volume_get_material(RID p_fog_volume) const;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
+ Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+};
+
+} // namespace RendererRD
+
+#endif // !FOG_RD_H
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index f3be4a7085..a749e7d5bc 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -33,7 +33,6 @@
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@@ -184,7 +183,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
voxel_gi->version++;
voxel_gi->data_version++;
- voxel_gi->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ voxel_gi->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const {
@@ -312,19 +311,6 @@ float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
return voxel_gi->normal_bias;
}
-void GI::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->anisotropy_strength = p_strength;
-}
-
-float GI::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->anisotropy_strength;
-}
-
void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
@@ -390,7 +376,6 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_gi->storage;
gi = p_gi;
num_cascades = p_env->sdfgi_cascades;
min_cell_size = p_env->sdfgi_min_cell_size;
@@ -1287,7 +1272,7 @@ void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSk
if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().srgb_to_linear();
+ Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear();
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
@@ -1636,7 +1621,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con
}
for (uint32_t v = 0; v < p_view_count; v++) {
- RendererStorageRD::store_camera(p_camera_with_transforms[v], scene_data.projection[v]);
+ RendererRD::MaterialStorage::store_camera(p_camera_with_transforms[v], scene_data.projection[v]);
}
RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data, RD::BARRIER_MASK_RASTER);
@@ -3218,12 +3203,10 @@ GI::~GI() {
singleton = nullptr;
}
-void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+void GI::init(RendererSceneSkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
-
/* GI */
{
@@ -3633,8 +3616,6 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
}
- print_line("Allocating GI buffers"); // TESTING REMOVE BEFORE MERGING
-
// Remember the view count we're using
rb->rbgi.view_count = p_view_count;
@@ -3681,7 +3662,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
}
for (uint32_t v = 0; v < p_view_count; v++) {
- RendererStorageRD::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ RendererRD::MaterialStorage::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
@@ -3689,7 +3670,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
}
// Note that we will be ignoring the origin of this transform.
- RendererStorageRD::store_transform(p_cam_transform, scene_data.cam_transform);
+ RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform);
scene_data.screen_size[0] = rb->internal_width;
scene_data.screen_size[1] = rb->internal_height;
@@ -3923,7 +3904,6 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RID GI::voxel_gi_instance_create(RID p_base) {
VoxelGIInstance voxel_gi;
voxel_gi.gi = this;
- voxel_gi.storage = storage;
voxel_gi.probe = p_base;
RID rid = voxel_gi_instance_owner.make_rid(voxel_gi);
return rid;
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index b6ecfe42ea..294b8d3cfd 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -37,7 +37,6 @@
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h"
@@ -47,8 +46,8 @@
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/storage/utilities.h"
// Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
struct RenderDataRD;
@@ -84,16 +83,13 @@ public:
bool interior = false;
bool use_two_bounces = false;
- float anisotropy_strength = 0.5;
-
uint32_t version = 1;
uint32_t data_version = 1;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
private:
- RendererStorageRD *storage = nullptr;
static GI *singleton;
/* VOXEL GI STORAGE */
@@ -418,9 +414,6 @@ public:
virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override;
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override;
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override;
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override;
-
virtual uint32_t voxel_gi_get_version(RID p_probe) const override;
uint32_t voxel_gi_get_data_version(RID p_probe);
@@ -435,7 +428,6 @@ public:
struct VoxelGIInstance {
// access to our containers
- RendererStorageRD *storage = nullptr;
GI *gi = nullptr;
RID probe;
@@ -559,7 +551,6 @@ public:
};
// access to our containers
- RendererStorageRD *storage = nullptr;
GI *gi = nullptr;
// used for rendering (voxelization)
@@ -780,7 +771,7 @@ public:
GI();
~GI();
- void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky);
+ void init(RendererSceneSkyRD *p_sky);
void free();
SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index c7048289c8..f759fa3aa5 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -30,6 +30,7 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
@@ -345,7 +346,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -435,7 +436,7 @@ void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferData
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
} else {
tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
@@ -448,7 +449,7 @@ void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferData
fb.push_back(rb->normal_roughness_buffer);
rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count);
} else {
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.samples = rb->texture_samples;
rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -812,15 +813,15 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
CameraMatrix projection = correction * p_render_data->cam_projection;
//store camera into ubo
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
+ RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
projection = correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x;
scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y;
@@ -836,10 +837,10 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.pancake_shadows = p_pancake_shadows;
- RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
@@ -934,7 +935,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
Basis sky_transform = environment_get_sky_orientation(p_render_data->environment);
sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
@@ -1005,15 +1006,15 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection;
//store camera into ubo
- RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix);
- RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix);
+ RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix);
+ RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix);
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
prev_projection = prev_correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]);
}
scene_state.prev_ubo.taa_jitter[0] = p_render_data->prev_taa_jitter.x;
scene_state.prev_ubo.taa_jitter[1] = p_render_data->prev_taa_jitter.y;
@@ -1069,11 +1070,11 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
}
if (inst->store_transform_cache) {
- RendererStorageRD::store_transform(inst->transform, instance_data.transform);
- RendererStorageRD::store_transform(inst->prev_transform, instance_data.prev_transform);
+ RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform);
+ RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform);
} else {
- RendererStorageRD::store_transform(Transform3D(), instance_data.transform);
- RendererStorageRD::store_transform(Transform3D(), instance_data.prev_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform);
}
instance_data.flags = inst->flags_cache;
@@ -1397,7 +1398,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
- RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@@ -1798,7 +1799,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ RendererCompositorRD::singleton->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -2189,7 +2190,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
to_bounds.origin = p_bounds.position;
to_bounds.basis.scale(p_bounds.size);
- RendererStorageRD::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds);
+ RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds);
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2888,7 +2889,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
- storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
}
//shadow
@@ -3131,16 +3132,16 @@ void RenderForwardClustered::_update_dirty_geometry_instances() {
}
}
-void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL:
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
@@ -3151,12 +3152,12 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
} break;
}
}
-void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
}
RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+ RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
GeometryInstanceForwardClustered *ginstance = geometry_instance_alloc.alloc();
@@ -3420,8 +3421,7 @@ void RenderForwardClustered::_update_shader_quality_settings() {
_base_uniforms_changed(); //also need this
}
-RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
- RendererSceneRenderRD(p_storage) {
+RenderForwardClustered::RenderForwardClustered() {
singleton = this;
/* SCENE SHADER */
@@ -3453,7 +3453,7 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
}
- scene_shader.init(p_storage, defines);
+ scene_shader.init(defines);
}
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 83f69e0674..9e1f1b9954 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -36,8 +36,8 @@
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
namespace RendererSceneRenderImplementation {
@@ -541,7 +541,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
bool mirror = false;
bool dirty_dependencies = false;
- RendererStorage::DependencyTracker dependency_tracker;
+ DependencyTracker dependency_tracker;
};
Data *data = nullptr;
@@ -550,8 +550,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
dirty_list_element(this) {}
};
- static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
- static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list;
@@ -683,7 +683,7 @@ public:
virtual bool free(RID p_rid) override;
- RenderForwardClustered(RendererStorageRD *p_storage);
+ RenderForwardClustered();
~RenderForwardClustered();
};
} // namespace RendererSceneRenderImplementation
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 aada989bcb..1951bfe915 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
@@ -520,9 +520,8 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() {
material_storage->material_free(default_material);
}
-void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+void SceneShaderForwardClustered::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{
Vector<String> shader_versions;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index ffa3893b6a..1cfe723174 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -32,7 +32,6 @@
#define RSSR_SCENE_SHADER_FC_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
namespace RendererSceneRenderImplementation {
@@ -42,8 +41,6 @@ private:
static SceneShaderForwardClustered *singleton;
public:
- RendererStorageRD *storage = nullptr;
-
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
SHADER_VERSION_DEPTH_PASS_DP,
@@ -249,7 +246,7 @@ public:
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
- void init(RendererStorageRD *p_storage, const String p_defines);
+ void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 25acd2e25f..e1855ddb36 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -465,7 +465,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
- RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@@ -1534,15 +1534,15 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
CameraMatrix projection = correction * p_render_data->cam_projection;
//store camera into ubo
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
+ RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
+ RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
for (uint32_t v = 0; v < p_render_data->view_count; v++) {
projection = correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x;
scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y;
@@ -1555,10 +1555,10 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.pancake_shadows = p_pancake_shadows;
- RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
@@ -1648,7 +1648,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
Basis sky_transform = environment_get_sky_orientation(p_render_data->environment);
sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
@@ -1866,9 +1866,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
GeometryInstanceForwardMobile::PushConstant push_constant;
if (inst->store_transform_cache) {
- RendererStorageRD::store_transform(inst->transform, push_constant.transform);
+ RendererRD::MaterialStorage::store_transform(inst->transform, push_constant.transform);
} else {
- RendererStorageRD::store_transform(Transform3D(), push_constant.transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), push_constant.transform);
}
push_constant.flags = inst->flags_cache;
@@ -2032,7 +2032,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
/* Geometry instance */
RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+ RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
GeometryInstanceForwardMobile *ginstance = geometry_instance_alloc.alloc();
@@ -2373,7 +2373,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
- storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
}
//shadow
@@ -2609,16 +2609,16 @@ void RenderForwardMobile::_update_dirty_geometry_instances() {
}
}
-void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL:
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
@@ -2629,7 +2629,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
} break;
}
}
-void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
}
@@ -2695,8 +2695,7 @@ void RenderForwardMobile::_update_shader_quality_settings() {
_base_uniforms_changed(); //also need this
}
-RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
- RendererSceneRenderRD(p_storage) {
+RenderForwardMobile::RenderForwardMobile() {
singleton = this;
sky.set_texture_format(_render_buffers_get_color_format());
@@ -2728,7 +2727,7 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
}
- scene_shader.init(p_storage, defines);
+ scene_shader.init(defines);
// !BAS! maybe we need a mobile version of this setting?
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 82e6c52c43..473a58045c 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -35,7 +35,7 @@
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
namespace RendererSceneRenderImplementation {
@@ -597,7 +597,7 @@ protected:
bool dirty_dependencies = false;
- RendererStorage::DependencyTracker dependency_tracker;
+ DependencyTracker dependency_tracker;
};
Data *data = nullptr;
@@ -613,8 +613,8 @@ protected:
public:
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
- static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
- static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
@@ -668,7 +668,7 @@ public:
virtual bool is_volumetric_supported() const override;
virtual uint32_t get_max_elements() const override;
- RenderForwardMobile(RendererStorageRD *p_storage);
+ RenderForwardMobile();
~RenderForwardMobile();
};
} // namespace RendererSceneRenderImplementation
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index f66ad529de..dd00dc2bf9 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -466,8 +466,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
singleton = this;
}
-void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
- storage = p_storage;
+void SceneShaderForwardMobile::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
/* SCENE SHADER */
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index f325d5c0a5..88c2143b09 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -32,7 +32,6 @@
#define RSSR_SCENE_SHADER_FM_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h"
namespace RendererSceneRenderImplementation {
@@ -40,7 +39,6 @@ namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
- RendererStorageRD *storage = nullptr;
public:
enum ShaderVersion {
@@ -207,7 +205,7 @@ public:
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
- void init(RendererStorageRD *p_storage, const String p_defines);
+ void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 3c2f3f8a42..b87b189d53 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -2270,10 +2270,9 @@ void RendererCanvasRenderRD::set_time(double p_time) {
void RendererCanvasRenderRD::update() {
}
-RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
+RendererCanvasRenderRD::RendererCanvasRenderRD() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{ //create default samplers
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 04881ce7e6..2ab5a7c831 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -34,15 +34,13 @@
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererStorageRD *storage = nullptr;
-
enum {
BASE_UNIFORM_SET = 0,
MATERIAL_UNIFORM_SET = 1,
@@ -462,7 +460,7 @@ public:
void set_time(double p_time);
void update();
bool free(RID p_rid);
- RendererCanvasRenderRD(RendererStorageRD *p_storage);
+ RendererCanvasRenderRD();
~RendererCanvasRenderRD();
};
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 759b8690eb..a61172c8f5 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -154,12 +154,14 @@ uint64_t RendererCompositorRD::frame = 1;
void RendererCompositorRD::finalize() {
memdelete(scene);
memdelete(canvas);
- memdelete(storage);
+ memdelete(effects);
+ memdelete(fog);
memdelete(particles_storage);
memdelete(light_storage);
memdelete(mesh_storage);
memdelete(material_storage);
memdelete(texture_storage);
+ memdelete(utilities);
//only need to erase these, the rest are erased by cascade
blit.shader.version_free(blit.shader_version);
@@ -287,28 +289,29 @@ RendererCompositorRD::RendererCompositorRD() {
singleton = this;
+ utilities = memnew(RendererRD::Utilities);
texture_storage = memnew(RendererRD::TextureStorage);
material_storage = memnew(RendererRD::MaterialStorage);
mesh_storage = memnew(RendererRD::MeshStorage);
light_storage = memnew(RendererRD::LightStorage);
particles_storage = memnew(RendererRD::ParticlesStorage);
- storage = memnew(RendererStorageRD);
- canvas = memnew(RendererCanvasRenderRD(storage));
+ fog = memnew(RendererRD::Fog);
+ canvas = memnew(RendererCanvasRenderRD());
back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
if (back_end || textures_per_stage < 48) {
- scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
+ scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile());
} else { // back_end == false
// default to our high end renderer
- scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
+ scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered());
}
scene->init();
// now we're ready to create our effects,
- storage->init_effects(!scene->_render_buffers_can_be_storage());
+ effects = memnew(EffectsRD(!scene->_render_buffers_can_be_storage()));
}
RendererCompositorRD::~RendererCompositorRD() {
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 12bcfc4684..2be55743fb 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -34,28 +34,32 @@
#include "core/os/os.h"
#include "core/templates/thread_work_pool.h"
#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/effects_rd.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h"
#include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h"
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
UniformSetCacheRD *uniform_set_cache = nullptr;
RendererCanvasRenderRD *canvas = nullptr;
+ RendererRD::Utilities *utilities = nullptr;
RendererRD::LightStorage *light_storage = nullptr;
RendererRD::MaterialStorage *material_storage = nullptr;
RendererRD::MeshStorage *mesh_storage = nullptr;
RendererRD::ParticlesStorage *particles_storage = nullptr;
RendererRD::TextureStorage *texture_storage = nullptr;
- RendererStorageRD *storage = nullptr;
+ RendererRD::Fog *fog = nullptr;
+ EffectsRD *effects = nullptr;
RendererSceneRenderRD *scene = nullptr;
enum BlitMode {
@@ -98,6 +102,7 @@ protected:
static uint64_t frame;
public:
+ RendererUtilities *get_utilities() { return utilities; };
RendererLightStorage *get_light_storage() { return light_storage; }
RendererMaterialStorage *get_material_storage() { return material_storage; }
RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
@@ -107,7 +112,8 @@ public:
ERR_FAIL_NULL_V(scene, nullptr);
return scene->get_gi();
}
- RendererStorage *get_storage() { return storage; }
+ RendererFog *get_fog() { return fog; }
+ EffectsRD *get_effects() { return effects; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index eb4bc3d535..5185d537ec 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@@ -534,7 +535,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
return panorama;
} else {
const float bg_energy = env->bg_energy;
- Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color);
+ Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : env->bg_color);
panorama_color = panorama_color.srgb_to_linear();
panorama_color.r *= bg_energy;
panorama_color.g *= bg_energy;
@@ -759,7 +760,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
atlas->reflections.resize(atlas->count);
for (int i = 0; i < atlas->count; i++) {
- atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
+ atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
for (int j = 0; j < 6; j++) {
atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
}
@@ -829,7 +830,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
// Using real time reflections, all roughness is done in one step
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(false);
rpi->rendering = false;
rpi->processing_side = 0;
rpi->processing_layer = 1;
@@ -837,7 +838,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
}
if (rpi->processing_layer > 1) {
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality);
rpi->processing_layer++;
if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
rpi->rendering = false;
@@ -848,7 +849,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
return false;
} else {
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality);
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality);
}
rpi->processing_side++;
@@ -1968,7 +1969,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
_allocate_blur_textures(rb);
}
- storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
+ RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
}
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
@@ -1979,7 +1980,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (!can_use_effects) {
//just copy
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
+ RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
return;
}
@@ -2019,8 +2020,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
+ RendererCompositorRD::singleton->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -2145,7 +2146,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
- storage->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set);
+ RendererCompositorRD::singleton->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set);
}
void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) {
@@ -2306,7 +2307,7 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen
transform.set_origin(Vector3(0.0, 0.0, 0.0));
CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse();
- storage->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set);
+ RendererCompositorRD::singleton->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set);
rb->ss_effects.last_frame_projection = projection;
rb->ss_effects.last_frame_transform = transform;
}
@@ -2354,7 +2355,7 @@ void RendererSceneRenderRD::_process_taa(RID p_render_buffers, RID p_velocity_bu
RD::get_singleton()->draw_command_begin_label("TAA");
if (!just_allocated) {
- storage->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far);
+ RendererCompositorRD::singleton->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far);
copy_effects->copy_to_rect(rb->taa.temp, rb->internal_texture, Rect2(0, 0, rb->internal_width, rb->internal_height));
}
@@ -2492,9 +2493,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
double step = env->auto_exp_speed * time_step;
if (can_use_storage) {
- storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
} else {
- storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
}
// Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
@@ -2639,7 +2640,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
- storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
+ RendererCompositorRD::singleton->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
RD::get_singleton()->draw_command_end_label();
}
@@ -3097,7 +3098,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
} else {
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
@@ -3364,7 +3365,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
Transform3D transform = rpi->transform;
Transform3D proj = (p_camera_inverse_transform * transform).inverse();
- RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix);
+ RendererRD::MaterialStorage::store_transform(proj, reflection_ubo.local_matrix);
if (current_cluster_builder != nullptr) {
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents);
@@ -3482,7 +3483,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale;
light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
+ RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
Vector2 uv_scale = li->shadow_transform[j].uv_scale;
uv_scale *= atlas_rect.size; //adapt to atlas size
@@ -3727,7 +3728,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
if (type == RS::LIGHT_OMNI) {
Transform3D proj = (inverse_transform * light_transform).inverse();
- RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
+ RendererRD::MaterialStorage::store_transform(proj, light_data.shadow_matrix);
if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
// Only enable PCSS-like soft shadows if blurring is enabled.
@@ -3746,7 +3747,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
bias.set_light_bias();
CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
+ RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix);
if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
// Only enable PCSS-like soft shadows if blurring is enabled.
@@ -3865,7 +3866,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
- RendererStorageRD::store_transform(to_decal_xform, dd.xform);
+ RendererRD::MaterialStorage::store_transform(to_decal_xform, dd.xform);
Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
@@ -3903,7 +3904,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.normal_rect[3] = rect.size.y;
Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
- RendererStorageRD::store_basis_3x4(normal_xform, dd.normal_xform);
+ RendererRD::MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform);
} else {
dd.normal_rect[0] = 0;
dd.normal_rect[1] = 0;
@@ -4326,8 +4327,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- storage->store_transform(to_prev_cam_view, params.to_prev_view);
- storage->store_transform(p_cam_transform, params.transform);
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+ RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform);
RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
@@ -4389,7 +4390,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
ERR_FAIL_COND(!fog_volume_instance);
RID fog_volume = fog_volume_instance->volume;
- RID fog_material = storage->fog_volume_get_material(fog_volume);
+ RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume);
FogMaterialData *material = nullptr;
@@ -4418,8 +4419,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
Vector3i kernel_size = Vector3i();
Vector3 position = fog_volume_instance->transform.get_origin();
- RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume);
- Vector3 extents = storage->fog_volume_get_extents(fog_volume);
+ RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
+ Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume);
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
// Local fog volume.
@@ -4462,8 +4463,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
volumetric_fog.push_constant.corner[0] = min.x;
volumetric_fog.push_constant.corner[1] = min.y;
volumetric_fog.push_constant.corner[2] = min.z;
- volumetric_fog.push_constant.shape = uint32_t(storage->fog_volume_get_shape(fog_volume));
- storage->store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform);
+ volumetric_fog.push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
+ RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
@@ -4808,7 +4809,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- storage->store_transform(to_prev_cam_view, params.to_prev_view);
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
@@ -4829,7 +4830,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
Basis sky_transform = env->sky_orientation;
sky_transform = sky_transform.inverse() * p_cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
@@ -5040,7 +5041,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
invalidate_uniform_set = true;
}
- storage->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
+ RendererCompositorRD::singleton->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
}
if (p_use_ssao) {
@@ -5189,7 +5190,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
if (p_render_buffers.is_valid()) {
clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
} else {
- clear_color = storage->get_default_clear_color();
+ clear_color = RSG::texture_storage->get_default_clear_color();
}
//assign render indices to voxel_gi_instances
@@ -5754,8 +5755,7 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
return GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements");
}
-RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
- storage = p_storage;
+RendererSceneRenderRD::RendererSceneRenderRD() {
singleton = this;
}
@@ -5769,12 +5769,12 @@ void RendererSceneRenderRD::init() {
/* SKY SHADER */
- sky.init(storage);
+ sky.init();
/* GI */
if (is_dynamic_gi_supported()) {
- gi.init(storage, &sky);
+ gi.init(&sky);
}
{ //decals
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 3f03f857f7..e8296882c9 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -41,7 +41,6 @@
#include "servers/rendering/renderer_rd/environment/gi.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/renderer_scene.h"
@@ -102,7 +101,6 @@ class RendererSceneRenderRD : public RendererSceneRender {
friend RendererRD::GI;
protected:
- RendererStorageRD *storage = nullptr;
RendererRD::BokehDOF *bokeh_dof = nullptr;
RendererRD::CopyEffects *copy_effects = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
@@ -1512,7 +1510,7 @@ public:
void init();
- RendererSceneRenderRD(RendererStorageRD *p_storage);
+ RendererSceneRenderRD();
~RendererSceneRenderRD();
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index b3b9b86aa8..73175d3cf3 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -37,6 +37,7 @@
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/rendering_server_globals.h"
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
@@ -329,13 +330,13 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
coefficient_buffer = RID();
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
+void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
//recreate radiance and all data
int mipmaps = p_mipmaps;
uint32_t w = p_size, h = p_size;
- EffectsRD *effects = p_storage->get_effects();
+ EffectsRD *effects = RendererCompositorRD::singleton->get_effects();
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
bool prefer_raster_effects = effects->get_prefer_raster_effects();
@@ -437,7 +438,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
+void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -495,7 +496,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
+void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -564,7 +565,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren
RD::get_singleton()->draw_command_end_label(); // Filter radiance
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
+void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised");
bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
@@ -591,7 +592,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora
////////////////////////////////////////////////////////////////////////////////
// RendererSceneSkyRD::Sky
-void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
+void RendererSceneSkyRD::Sky::free() {
if (radiance.is_valid()) {
RD::get_singleton()->free(radiance);
radiance = RID();
@@ -614,12 +615,12 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
}
if (material.is_valid()) {
- p_storage->free(material);
+ RSG::material_storage->material_free(material);
material = RID();
}
}
-RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) {
@@ -795,10 +796,9 @@ RendererSceneSkyRD::RendererSceneSkyRD() {
sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections");
}
-void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+void RendererSceneSkyRD::init() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{
// Start with the directional lights for the sky
@@ -1387,7 +1387,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
@@ -1406,7 +1406,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
@@ -1421,7 +1421,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
@@ -1430,22 +1430,22 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::get_singleton()->draw_command_end_label();
if (sky_mode == RS::SKY_MODE_REALTIME) {
- sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
+ sky->reflection.create_reflection_fast_filter(sky_use_cubemap_array);
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size());
}
} else {
if (update_single_frame) {
for (int i = 1; i < max_processing_layer; i++) {
- sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, i, sky_ggx_samples_quality);
+ sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, i, sky_ggx_samples_quality);
}
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size());
}
} else {
if (sky_use_cubemap_array) {
// Multi-Frame so just update the first array level
- sky->reflection.update_reflection_mipmaps(storage, 0, 1);
+ sky->reflection.update_reflection_mipmaps(0, 1);
}
}
sky->processing_layer = 1;
@@ -1455,10 +1455,10 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
} else {
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
- sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality);
+ sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality);
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, sky->processing_layer, sky->processing_layer + 1);
+ sky->reflection.update_reflection_mipmaps(sky->processing_layer, sky->processing_layer + 1);
}
sky->processing_layer++;
@@ -1536,7 +1536,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (shader_data->uses_quarter_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
@@ -1549,7 +1549,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (shader_data->uses_half_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
@@ -1563,7 +1563,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
RID texture_uniform_set;
if (sky) {
- texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
} else {
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
@@ -1634,7 +1634,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (shader_data->uses_quarter_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
@@ -1647,7 +1647,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (shader_data->uses_half_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
@@ -1729,7 +1729,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
RID texture_uniform_set;
if (sky) {
- texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
} else {
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
@@ -1777,7 +1777,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
+ sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
} else {
//regular cubemap, lower quality (aliasing, less memory)
@@ -1792,7 +1792,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
+ sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
}
texture_set_dirty = true;
}
@@ -1872,7 +1872,7 @@ void RendererSceneSkyRD::free_sky(RID p_sky) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
- sky->free(storage);
+ sky->free();
sky_owner.free(p_sky);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 83a8fe6e77..a8ee406abc 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -33,11 +33,13 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/shader_compiler.h"
// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;
@@ -63,7 +65,6 @@ public:
};
private:
- RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -211,10 +212,10 @@ public:
Vector<Layer> layers;
void clear_reflection_data();
- void update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
- void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays);
- void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
- void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
+ void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
+ void create_reflection_fast_filter(bool p_use_arrays);
+ void create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
+ void update_reflection_mipmaps(int p_start, int p_end);
};
/* Sky shader */
@@ -267,9 +268,9 @@ public:
Vector3 prev_position;
float prev_time;
- void free(RendererStorageRD *p_storage);
+ void free();
- RID get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd);
+ RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd);
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
@@ -289,7 +290,7 @@ public:
static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
RendererSceneSkyRD();
- void init(RendererStorageRD *p_storage);
+ void init();
void set_texture_format(RD::DataFormat p_texture_format);
~RendererSceneSkyRD();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
deleted file mode 100644
index d41129d678..0000000000
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*************************************************************************/
-/* renderer_storage_rd.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RENDERING_SERVER_STORAGE_RD_H
-#define RENDERING_SERVER_STORAGE_RD_H
-
-#include "core/templates/list.h"
-#include "core/templates/local_vector.h"
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_rd/effects_rd.h"
-#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/rendering_device.h"
-#include "servers/rendering/shader_compiler.h"
-
-class RendererStorageRD : public RendererStorage {
-public:
- static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.rows[0][0];
- p_array[1] = p_mtx.basis.rows[1][0];
- p_array[2] = p_mtx.basis.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.basis.rows[0][1];
- p_array[5] = p_mtx.basis.rows[1][1];
- p_array[6] = p_mtx.basis.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.basis.rows[0][2];
- p_array[9] = p_mtx.basis.rows[1][2];
- p_array[10] = p_mtx.basis.rows[2][2];
- p_array[11] = 0;
- p_array[12] = p_mtx.origin.x;
- p_array[13] = p_mtx.origin.y;
- p_array[14] = p_mtx.origin.z;
- p_array[15] = 1;
- }
-
- static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.rows[0][0];
- p_array[1] = p_mtx.rows[1][0];
- p_array[2] = p_mtx.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.rows[0][1];
- p_array[5] = p_mtx.rows[1][1];
- p_array[6] = p_mtx.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.rows[0][2];
- p_array[9] = p_mtx.rows[1][2];
- p_array[10] = p_mtx.rows[2][2];
- p_array[11] = 0;
- }
-
- static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.rows[0][0];
- p_array[1] = p_mtx.rows[1][0];
- p_array[2] = p_mtx.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.rows[0][1];
- p_array[5] = p_mtx.rows[1][1];
- p_array[6] = p_mtx.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.rows[0][2];
- p_array[9] = p_mtx.rows[1][2];
- p_array[10] = p_mtx.rows[2][2];
- p_array[11] = 0;
- }
-
- static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.rows[0][0];
- p_array[1] = p_mtx.basis.rows[0][1];
- p_array[2] = p_mtx.basis.rows[0][2];
- p_array[3] = p_mtx.origin.x;
- p_array[4] = p_mtx.basis.rows[1][0];
- p_array[5] = p_mtx.basis.rows[1][1];
- p_array[6] = p_mtx.basis.rows[1][2];
- p_array[7] = p_mtx.origin.y;
- p_array[8] = p_mtx.basis.rows[2][0];
- p_array[9] = p_mtx.basis.rows[2][1];
- p_array[10] = p_mtx.basis.rows[2][2];
- p_array[11] = p_mtx.origin.z;
- }
-
- static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
- }
-
- static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
- for (int i = 0; i < 128; i++) {
- p_array[i] = p_kernel[i];
- }
- }
-
-private:
- /* FOG VOLUMES */
-
- struct FogVolume {
- RID material;
- Vector3 extents = Vector3(1, 1, 1);
-
- RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<FogVolume, true> fog_volume_owner;
-
- /* visibility_notifier */
-
- struct VisibilityNotifier {
- AABB aabb;
- Callable enter_callback;
- Callable exit_callback;
- Dependency dependency;
- };
-
- mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
-
- /* EFFECTS */
-
- EffectsRD *effects = nullptr;
-
-public:
- //internal usage
-
- void base_update_dependency(RID p_base, DependencyTracker *p_instance);
-
- /* FOG VOLUMES */
-
- virtual RID fog_volume_allocate();
- virtual void fog_volume_initialize(RID p_rid);
-
- virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape);
- virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents);
- virtual void fog_volume_set_material(RID p_fog_volume, RID p_material);
- virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const;
- virtual RID fog_volume_get_material(RID p_fog_volume) const;
- virtual AABB fog_volume_get_aabb(RID p_fog_volume) const;
- virtual Vector3 fog_volume_get_extents(RID p_fog_volume) const;
-
- /* VISIBILITY NOTIFIER */
-
- virtual RID visibility_notifier_allocate();
- virtual void visibility_notifier_initialize(RID p_notifier);
- virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
- virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable);
-
- virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
- virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
-
- RS::InstanceType get_base_type(RID p_rid) const;
-
- bool free(RID p_rid);
-
- bool has_os_feature(const String &p_feature) const;
-
- void update_dirty_resources();
-
- void set_debug_generate_wireframes(bool p_generate) {}
-
- //keep cached since it can be called form any thread
- uint64_t texture_mem_cache = 0;
- uint64_t buffer_mem_cache = 0;
- uint64_t total_mem_cache = 0;
-
- virtual void update_memory_info();
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info);
-
- String get_video_adapter_name() const;
- String get_video_adapter_vendor() const;
- RenderingDevice::DeviceType get_video_adapter_type() const;
- String get_video_adapter_api_version() const;
-
- virtual void capture_timestamps_begin();
- virtual void capture_timestamp(const String &p_name);
- virtual uint32_t get_captured_timestamps_count() const;
- virtual uint64_t get_captured_timestamps_frame() const;
- virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const;
- virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
- virtual String get_captured_timestamp_name(uint32_t p_index) const;
-
- static RendererStorageRD *base_singleton;
-
- void init_effects(bool p_prefer_raster_effects);
- EffectsRD *get_effects();
-
- RendererStorageRD();
- ~RendererStorageRD();
-};
-
-#endif // RASTERIZER_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub
index 05663226c0..d352743908 100644
--- a/servers/rendering/renderer_rd/shaders/SCsub
+++ b/servers/rendering/renderer_rd/shaders/SCsub
@@ -10,7 +10,7 @@ if "RD_GLSL" in env["BUILDERS"]:
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
# compile shaders
for glsl_file in glsl_files:
diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub
index fc513d3fb9..741da8fe69 100644
--- a/servers/rendering/renderer_rd/shaders/effects/SCsub
+++ b/servers/rendering/renderer_rd/shaders/effects/SCsub
@@ -10,7 +10,7 @@ if "RD_GLSL" in env["BUILDERS"]:
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
# compile shaders
for glsl_file in glsl_files:
diff --git a/servers/rendering/renderer_rd/shaders/environment/SCsub b/servers/rendering/renderer_rd/shaders/environment/SCsub
index fc513d3fb9..741da8fe69 100644
--- a/servers/rendering/renderer_rd/shaders/environment/SCsub
+++ b/servers/rendering/renderer_rd/shaders/environment/SCsub
@@ -10,7 +10,7 @@ if "RD_GLSL" in env["BUILDERS"]:
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
# compile shaders
for glsl_file in glsl_files:
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 56a4525b8e..e65f676785 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -156,12 +156,12 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
} break;
case RS::LIGHT_PARAM_SIZE: {
if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
//changing from no size to size and the opposite
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
} break;
default: {
@@ -177,7 +177,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_projector(RID p_light, RID p_texture) {
@@ -199,7 +199,7 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
if (light->projector.is_valid()) {
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
}
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
}
@@ -217,7 +217,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
@@ -237,7 +237,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->reverse_cull = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@@ -247,7 +247,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod
light->bake_mode = p_bake_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
@@ -257,7 +257,7 @@ void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade)
light->max_sdfgi_cascade = p_cascade;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@@ -267,7 +267,7 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo
light->omni_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
@@ -283,7 +283,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec
light->directional_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@@ -292,7 +292,7 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable
light->directional_blend_splits = p_enable;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
@@ -387,7 +387,7 @@ void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionP
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
@@ -424,7 +424,7 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan
reflection_probe->max_distance = p_distance;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
@@ -435,7 +435,7 @@ void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_ex
return;
}
reflection_probe->extents = p_extents;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
@@ -443,7 +443,7 @@ void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
@@ -451,7 +451,7 @@ void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable)
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@@ -466,7 +466,7 @@ void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enabl
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
@@ -474,7 +474,7 @@ void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
@@ -491,7 +491,7 @@ void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_
reflection_probe->mesh_lod_threshold = p_ratio;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 3cc455692d..fb25e4da7e 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -35,6 +35,7 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/storage/light_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
@@ -61,7 +62,7 @@ struct Light {
RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
uint64_t version = 0;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* REFLECTION PROBE */
@@ -82,7 +83,7 @@ struct ReflectionProbe {
uint32_t cull_mask = (1 << 20) - 1;
float mesh_lod_threshold = 0.01;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* LIGHTMAP */
@@ -104,7 +105,7 @@ struct Lightmap {
int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
};
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
class LightStorage : public RendererLightStorage {
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 096d371b8d..fcd25852eb 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -2346,7 +2346,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
for (Material *E : shader->owners) {
Material *material = E;
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
}
@@ -2436,7 +2436,7 @@ void MaterialStorage::_material_uniform_set_erased(void *p_material) {
// if a texture is deleted, so re-create it.
MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
}
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
}
@@ -2466,7 +2466,7 @@ void MaterialStorage::_update_queued_materials() {
if (uniforms_changed) {
//some implementations such as 3D renderer cache the matreial uniform set, so update is required
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
}
}
@@ -2507,7 +2507,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
}
if (p_shader.is_null()) {
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
material->shader_id = 0;
return;
}
@@ -2530,7 +2530,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
@@ -2576,7 +2576,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material
material->data->set_next_pass(p_next_material);
}
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
@@ -2626,7 +2626,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li
}
}
-void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
p_instance->update_dependency(&material->dependency);
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index f83df05355..e35d5e7669 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -31,12 +31,14 @@
#ifndef MATERIAL_STORAGE_RD_H
#define MATERIAL_STORAGE_RD_H
+#include "core/math/camera_matrix.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
@@ -125,7 +127,7 @@ struct Material {
RID next_pass;
SelfList<Material> update_element;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
Material() :
update_element(this) {}
@@ -232,6 +234,86 @@ public:
MaterialStorage();
virtual ~MaterialStorage();
+ /* Helpers */
+
+ static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[1][0];
+ p_array[2] = p_mtx.basis.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.basis.rows[0][1];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.basis.rows[0][2];
+ p_array[9] = p_mtx.basis.rows[1][2];
+ p_array[10] = p_mtx.basis.rows[2][2];
+ p_array[11] = 0;
+ p_array[12] = p_mtx.origin.x;
+ p_array[13] = p_mtx.origin.y;
+ p_array[14] = p_mtx.origin.z;
+ p_array[15] = 1;
+ }
+
+ static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
+ p_array[11] = 0;
+ }
+
+ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
+ p_array[11] = 0;
+ }
+
+ static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[0][1];
+ p_array[2] = p_mtx.basis.rows[0][2];
+ p_array[3] = p_mtx.origin.x;
+ p_array[4] = p_mtx.basis.rows[1][0];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[1][2];
+ p_array[7] = p_mtx.origin.y;
+ p_array[8] = p_mtx.basis.rows[2][0];
+ p_array[9] = p_mtx.basis.rows[2][1];
+ p_array[10] = p_mtx.basis.rows[2][2];
+ p_array[11] = p_mtx.origin.z;
+ }
+
+ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ }
+ }
+ }
+
+ static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
+ for (int i = 0; i < 128; i++) {
+ p_array[i] = p_kernel[i];
+ }
+ }
+
/* Samplers */
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
@@ -317,7 +399,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 1e0d67f269..3875eb6615 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -210,6 +210,8 @@ void MeshStorage::mesh_free(RID p_rid) {
mesh_clear(p_rid);
mesh_set_shadow_mesh(p_rid, RID());
Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!mesh);
+
mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
@@ -218,7 +220,7 @@ void MeshStorage::mesh_free(RID p_rid) {
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
mesh_owner.free(p_rid);
@@ -429,12 +431,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
mesh->material_cache.clear();
@@ -501,7 +503,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear();
}
@@ -692,7 +694,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
shadow_mesh->shadow_owners.insert(mesh);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
void MeshStorage::mesh_clear(RID p_mesh) {
@@ -740,12 +742,12 @@ void MeshStorage::mesh_clear(RID p_mesh) {
_mesh_instance_clear(mi);
}
mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
@@ -1209,7 +1211,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}
int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
@@ -1243,7 +1245,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
}
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
@@ -1602,7 +1604,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
const float *data = p_buffer.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1644,7 +1646,7 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
multimesh->visible_instances = p_visible;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
@@ -1703,7 +1705,7 @@ void MeshStorage::_update_dirty_multimeshes() {
//aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1781,7 +1783,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
}
}
- skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA);
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_DATA);
}
int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
@@ -1902,7 +1904,7 @@ void MeshStorage::_update_dirty_skeletons() {
skeleton_dirty_list = skeleton->dirty_list;
- skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES);
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_BONES);
skeleton->version++;
@@ -1913,7 +1915,7 @@ void MeshStorage::_update_dirty_skeletons() {
skeleton_dirty_list = nullptr;
}
-void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) {
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 7ce019cf98..9cdda6bfca 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -35,8 +35,8 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
@@ -143,7 +143,7 @@ struct Mesh {
RID shadow_mesh;
HashSet<Mesh *> shadow_owners;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* Mesh Instance */
@@ -199,7 +199,7 @@ struct MultiMesh {
bool dirty = false;
MultiMesh *dirty_list = nullptr;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
/* Skeleton */
@@ -256,7 +256,7 @@ struct Skeleton {
uint64_t version = 1;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
class MeshStorage : public RendererMeshStorage {
@@ -672,7 +672,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
- virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) override;
void _update_dirty_skeletons();
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 58a96ed1f9..5200e0d318 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -30,7 +30,6 @@
#include "particles_storage.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/rendering_server_globals.h"
#include "texture_storage.h"
@@ -321,7 +320,7 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
@@ -356,7 +355,7 @@ void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
@@ -370,7 +369,7 @@ void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool
ERR_FAIL_COND(!particles);
particles->use_local_coords = p_enable;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
@@ -386,7 +385,7 @@ void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
@@ -419,7 +418,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
@@ -436,7 +435,7 @@ void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vec
particles->trail_bind_poses = p_bind_poses;
particles->trail_bind_poses_dirty = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
@@ -458,7 +457,7 @@ void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_mat
ERR_FAIL_COND(!particles);
particles->process_material = p_material;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
}
RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
@@ -545,7 +544,7 @@ void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_tran
int32_t idx = particles->emission_buffer->particle_count;
if (idx < particles->emission_buffer->particle_max) {
- RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
+ RendererRD::MaterialStorage::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
@@ -766,9 +765,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
frame_params.randomness = p_particles->randomness;
if (p_particles->use_local_coords) {
- RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), frame_params.emission_transform);
} else {
- RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ RendererRD::MaterialStorage::store_transform(p_particles->emission_transform, frame_params.emission_transform);
}
frame_params.cycle = p_particles->cycle_number;
@@ -858,7 +857,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
- RendererStorageRD::store_transform(to_collider, attr.transform);
+ RendererRD::MaterialStorage::store_transform(to_collider, attr.transform);
attr.strength = pc->attractor_strength;
attr.attenuation = pc->attractor_attenuation;
attr.directionality = pc->attractor_directionality;
@@ -906,7 +905,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
- RendererStorageRD::store_transform(to_collider, col.transform);
+ RendererRD::MaterialStorage::store_transform(to_collider, col.transform);
switch (pc->type) {
case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
@@ -1203,7 +1202,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
- RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+ RendererCompositorRD::singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
}
copy_push_constant.total_particles *= copy_push_constant.total_particles;
@@ -1383,7 +1382,7 @@ void ParticlesStorage::update_particles() {
}
for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
- RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
+ RendererRD::MaterialStorage::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
}
RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
@@ -1457,14 +1456,14 @@ void ParticlesStorage::update_particles() {
// In local mode, particle positions are calculated locally (relative to the node position)
// and they're also drawn locally.
// It works as expected, so we just pass an identity transform.
- RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
} else {
// In global mode, particle positions are calculated globally (relative to the canvas origin)
// but they're drawn locally.
// So, we need to pass the inverse of the emission transform to bring the
// particles to local coordinates before drawing.
Transform3D inv = particles->emission_transform.affine_inverse();
- RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform);
+ RendererRD::MaterialStorage::store_transform(inv, copy_push_constant.inv_emission_transform);
}
copy_push_constant.total_particles = total_amount;
@@ -1500,7 +1499,7 @@ void ParticlesStorage::update_particles() {
RD::get_singleton()->compute_list_end();
}
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1756,7 +1755,7 @@ void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_co
particles_collision->heightfield_texture = RID();
}
particles_collision->type = p_type;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
@@ -1770,7 +1769,7 @@ void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_col
ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
@@ -1778,7 +1777,7 @@ void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_colli
ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
@@ -1812,7 +1811,7 @@ void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_col
void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 115633d17a..70ac6f0349 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -37,9 +37,9 @@
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/storage/particles_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
@@ -226,7 +226,7 @@ struct Particles {
HashSet<RID> collisions;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
double trail_length = 1.0;
bool trails_enabled = false;
@@ -254,7 +254,7 @@ struct ParticlesCollision {
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
struct ParticlesCollisionInstance {
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 329c23bad0..1109357a74 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -1712,7 +1712,7 @@ void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->extents = p_extents;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
@@ -1736,7 +1736,7 @@ void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID
texture_add_to_decal_atlas(decal->textures[p_type]);
}
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL);
}
void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
@@ -1761,7 +1761,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 901f764085..7a96e6c6ed 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -33,8 +33,8 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
@@ -193,7 +193,7 @@ struct Decal {
float distance_fade_length = 1;
float normal_fade = 0.0;
- RendererStorage::Dependency dependency;
+ Dependency dependency;
};
struct RenderTarget {
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index 8c55ff1d0a..a1f62c16c7 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_storage_rd.cpp */
+/* utilities.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,195 +28,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_storage_rd.h"
-
-#include "core/config/engine.h"
-#include "core/config/project_settings.h"
-#include "core/io/resource_loader.h"
-#include "core/math/math_defs.h"
-#include "renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/environment/gi.h"
-#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
-#include "servers/rendering/rendering_server_globals.h"
-#include "servers/rendering/shader_language.h"
-
-/* FOG VOLUMES */
-
-RID RendererStorageRD::fog_volume_allocate() {
- return fog_volume_owner.allocate_rid();
-}
-void RendererStorageRD::fog_volume_initialize(RID p_rid) {
- fog_volume_owner.initialize_rid(p_rid, FogVolume());
-}
-
-void RendererStorageRD::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
-
- if (p_shape == fog_volume->shape) {
- return;
- }
-
- fog_volume->shape = p_shape;
- fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
+#include "utilities.h"
+#include "../environment/fog.h"
+#include "../environment/gi.h"
+#include "light_storage.h"
+#include "mesh_storage.h"
+#include "particles_storage.h"
+#include "texture_storage.h"
-void RendererStorageRD::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
+using namespace RendererRD;
- fog_volume->extents = p_extents;
- fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
+Utilities *Utilities::singleton = nullptr;
-void RendererStorageRD::fog_volume_set_material(RID p_fog_volume, RID p_material) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
- fog_volume->material = p_material;
+Utilities::Utilities() {
+ singleton = this;
}
-RID RendererStorageRD::fog_volume_get_material(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, RID());
-
- return fog_volume->material;
+Utilities::~Utilities() {
+ singleton = nullptr;
}
-RS::FogVolumeShape RendererStorageRD::fog_volume_get_shape(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
-
- return fog_volume->shape;
-}
+/* INSTANCES */
-AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, AABB());
-
- switch (fog_volume->shape) {
- case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
- case RS::FOG_VOLUME_SHAPE_CONE:
- case RS::FOG_VOLUME_SHAPE_CYLINDER:
- case RS::FOG_VOLUME_SHAPE_BOX: {
- AABB aabb;
- aabb.position = -fog_volume->extents;
- aabb.size = fog_volume->extents * 2;
- return aabb;
- }
- default: {
- // Need some size otherwise will get culled
- return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
- }
- }
-
- return AABB();
-}
-
-Vector3 RendererStorageRD::fog_volume_get_extents(RID p_fog_volume) const {
- const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, Vector3());
- return fog_volume->extents;
-}
-
-/* VISIBILITY NOTIFIER */
-
-RID RendererStorageRD::visibility_notifier_allocate() {
- return visibility_notifier_owner.allocate_rid();
-}
-void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
- visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
-}
-void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
- vn->aabb = p_aabb;
- vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
- vn->enter_callback = p_enter_callbable;
- vn->exit_callback = p_exit_callable;
-}
-
-AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
- const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND_V(!vn, AABB());
- return vn->aabb;
-}
-void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
-
- if (p_enter) {
- if (!vn->enter_callback.is_null()) {
- if (p_deferred) {
- vn->enter_callback.call_deferred(nullptr, 0);
- } else {
- Variant r;
- Callable::CallError ce;
- vn->enter_callback.call(nullptr, 0, r, ce);
- }
- }
- } else {
- if (!vn->exit_callback.is_null()) {
- if (p_deferred) {
- vn->exit_callback.call_deferred(nullptr, 0);
- } else {
- Variant r;
- Callable::CallError ce;
- vn->exit_callback.call(nullptr, 0, r, ce);
- }
- }
- }
-}
-
-/* misc */
-
-void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
- RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base);
- p_instance->update_dependency(&mesh->dependency);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
- RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base);
- p_instance->update_dependency(&multimesh->dependency);
- if (multimesh->mesh.is_valid()) {
- base_update_dependency(multimesh->mesh, p_instance);
- }
- } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
- RendererRD::ReflectionProbe *rp = RendererRD::LightStorage::get_singleton()->get_reflection_probe(p_base);
- p_instance->update_dependency(&rp->dependency);
- } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_base)) {
- RendererRD::Decal *decal = RendererRD::TextureStorage::get_singleton()->get_decal(p_base);
- p_instance->update_dependency(&decal->dependency);
- } else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_base)) {
- RendererRD::GI::VoxelGI *gip = RendererRD::GI::get_singleton()->get_voxel_gi(p_base);
- p_instance->update_dependency(&gip->dependency);
- } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_base)) {
- RendererRD::Lightmap *lm = RendererRD::LightStorage::get_singleton()->get_lightmap(p_base);
- p_instance->update_dependency(&lm->dependency);
- } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) {
- RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base);
- p_instance->update_dependency(&l->dependency);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) {
- RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base);
- p_instance->update_dependency(&p->dependency);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
- RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base);
- p_instance->update_dependency(&pc->dependency);
- } else if (fog_volume_owner.owns(p_base)) {
- FogVolume *fv = fog_volume_owner.get_or_null(p_base);
- p_instance->update_dependency(&fv->dependency);
- } else if (visibility_notifier_owner.owns(p_base)) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base);
- p_instance->update_dependency(&vn->dependency);
- }
-}
-
-RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
+RS::InstanceType Utilities::get_base_type(RID p_rid) const {
if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
return RS::INSTANCE_MESH;
}
@@ -244,49 +78,17 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
- if (fog_volume_owner.owns(p_rid)) {
+ if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
return RS::INSTANCE_FOG_VOLUME;
}
- if (visibility_notifier_owner.owns(p_rid)) {
+ if (owns_visibility_notifier(p_rid)) {
return RS::INSTANCE_VISIBLITY_NOTIFIER;
}
return RS::INSTANCE_NONE;
}
-void RendererStorageRD::update_dirty_resources() {
- RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
- RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
- RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
- RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
- RendererRD::TextureStorage::get_singleton()->update_decal_atlas();
-}
-
-bool RendererStorageRD::has_os_feature(const String &p_feature) const {
- if (!RD::get_singleton()) {
- return false;
- }
-
- if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- return false;
-}
-
-bool RendererStorageRD::free(RID p_rid) {
+bool Utilities::free(RID p_rid) {
if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) {
RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
} else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
@@ -317,16 +119,12 @@ bool RendererStorageRD::free(RID p_rid) {
RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid);
} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
- } else if (visibility_notifier_owner.owns(p_rid)) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);
- vn->dependency.deleted_notify(p_rid);
- visibility_notifier_owner.free(p_rid);
+ } else if (owns_visibility_notifier(p_rid)) {
+ visibility_notifier_free(p_rid);
} else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
- } else if (fog_volume_owner.owns(p_rid)) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
- fog_volume->dependency.deleted_notify(p_rid);
- fog_volume_owner.free(p_rid);
+ } else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
+ RendererRD::Fog::get_singleton()->fog_free(p_rid);
} else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid);
} else {
@@ -336,49 +134,182 @@ bool RendererStorageRD::free(RID p_rid) {
return true;
}
-void RendererStorageRD::init_effects(bool p_prefer_raster_effects) {
- effects = memnew(EffectsRD(p_prefer_raster_effects));
+/* DEPENDENCIES */
+
+void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
+ if (MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base);
+ p_instance->update_dependency(&mesh->dependency);
+ } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base);
+ p_instance->update_dependency(&multimesh->dependency);
+ if (multimesh->mesh.is_valid()) {
+ base_update_dependency(multimesh->mesh, p_instance);
+ }
+ } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
+ ReflectionProbe *rp = LightStorage::get_singleton()->get_reflection_probe(p_base);
+ p_instance->update_dependency(&rp->dependency);
+ } else if (TextureStorage::get_singleton()->owns_decal(p_base)) {
+ Decal *decal = TextureStorage::get_singleton()->get_decal(p_base);
+ p_instance->update_dependency(&decal->dependency);
+ } else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
+ GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base);
+ p_instance->update_dependency(&gip->dependency);
+ } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
+ Lightmap *lm = LightStorage::get_singleton()->get_lightmap(p_base);
+ p_instance->update_dependency(&lm->dependency);
+ } else if (LightStorage::get_singleton()->owns_light(p_base)) {
+ Light *l = LightStorage::get_singleton()->get_light(p_base);
+ p_instance->update_dependency(&l->dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ Particles *p = ParticlesStorage::get_singleton()->get_particles(p_base);
+ p_instance->update_dependency(&p->dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ ParticlesCollision *pc = ParticlesStorage::get_singleton()->get_particles_collision(p_base);
+ p_instance->update_dependency(&pc->dependency);
+ } else if (Fog::get_singleton()->owns_fog_volume(p_base)) {
+ Fog::FogVolume *fv = Fog::get_singleton()->get_fog_volume(p_base);
+ p_instance->update_dependency(&fv->dependency);
+ } else if (owns_visibility_notifier(p_base)) {
+ VisibilityNotifier *vn = get_visibility_notifier(p_base);
+ p_instance->update_dependency(&vn->dependency);
+ }
+}
+
+/* VISIBILITY NOTIFIER */
+
+RID Utilities::visibility_notifier_allocate() {
+ return visibility_notifier_owner.allocate_rid();
+}
+
+void Utilities::visibility_notifier_initialize(RID p_notifier) {
+ visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
+}
+
+void Utilities::visibility_notifier_free(RID p_notifier) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ vn->dependency.deleted_notify(p_notifier);
+ visibility_notifier_owner.free(p_notifier);
+}
+
+void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->aabb = p_aabb;
+ vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->enter_callback = p_enter_callbable;
+ vn->exit_callback = p_exit_callable;
+}
+
+AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const {
+ const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND_V(!vn, AABB());
+ return vn->aabb;
}
-EffectsRD *RendererStorageRD::get_effects() {
- ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet.");
- return effects;
+void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+
+ if (p_enter) {
+ if (!vn->enter_callback.is_null()) {
+ if (p_deferred) {
+ vn->enter_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->enter_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ } else {
+ if (!vn->exit_callback.is_null()) {
+ if (p_deferred) {
+ vn->exit_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->exit_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ }
}
-void RendererStorageRD::capture_timestamps_begin() {
+/* TIMING */
+
+void Utilities::capture_timestamps_begin() {
RD::get_singleton()->capture_timestamp("Frame Begin");
}
-void RendererStorageRD::capture_timestamp(const String &p_name) {
+void Utilities::capture_timestamp(const String &p_name) {
RD::get_singleton()->capture_timestamp(p_name);
}
-uint32_t RendererStorageRD::get_captured_timestamps_count() const {
+uint32_t Utilities::get_captured_timestamps_count() const {
return RD::get_singleton()->get_captured_timestamps_count();
}
-uint64_t RendererStorageRD::get_captured_timestamps_frame() const {
+uint64_t Utilities::get_captured_timestamps_frame() const {
return RD::get_singleton()->get_captured_timestamps_frame();
}
-uint64_t RendererStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const {
+uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);
}
-uint64_t RendererStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const {
+uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);
}
-String RendererStorageRD::get_captured_timestamp_name(uint32_t p_index) const {
+String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_name(p_index);
}
-void RendererStorageRD::update_memory_info() {
+/* MISC */
+
+void Utilities::update_dirty_resources() {
+ MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
+ MaterialStorage::get_singleton()->_update_queued_materials();
+ MeshStorage::get_singleton()->_update_dirty_multimeshes();
+ MeshStorage::get_singleton()->_update_dirty_skeletons();
+ TextureStorage::get_singleton()->update_decal_atlas();
+}
+
+bool Utilities::has_os_feature(const String &p_feature) const {
+ if (!RD::get_singleton()) {
+ return false;
+ }
+
+ if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ return false;
+}
+
+void Utilities::update_memory_info() {
texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);
buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);
total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);
}
-uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
+
+uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {
return texture_mem_cache;
} else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {
@@ -389,31 +320,18 @@ uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
return 0;
}
-String RendererStorageRD::get_video_adapter_name() const {
+String Utilities::get_video_adapter_name() const {
return RenderingDevice::get_singleton()->get_device_name();
}
-String RendererStorageRD::get_video_adapter_vendor() const {
+String Utilities::get_video_adapter_vendor() const {
return RenderingDevice::get_singleton()->get_device_vendor_name();
}
-RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
+RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
return RenderingDevice::get_singleton()->get_device_type();
}
-String RendererStorageRD::get_video_adapter_api_version() const {
+String Utilities::get_video_adapter_api_version() const {
return RenderingDevice::get_singleton()->get_device_api_version();
}
-
-RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
-
-RendererStorageRD::RendererStorageRD() {
- base_singleton = this;
-}
-
-RendererStorageRD::~RendererStorageRD() {
- if (effects) {
- memdelete(effects);
- effects = nullptr;
- }
-}
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h
new file mode 100644
index 0000000000..979e984546
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.h
@@ -0,0 +1,122 @@
+/*************************************************************************/
+/* utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef UTILITIES_RD_H
+#define UTILITIES_RD_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/storage/utilities.h"
+
+namespace RendererRD {
+
+/* VISIBILITY NOTIFIER */
+
+struct VisibilityNotifier {
+ AABB aabb;
+ Callable enter_callback;
+ Callable exit_callback;
+ Dependency dependency;
+};
+
+class Utilities : public RendererUtilities {
+private:
+ static Utilities *singleton;
+
+ /* VISIBILITY NOTIFIER */
+
+ mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
+
+ /* MISC */
+
+ //keep cached since it can be called form any thread
+ uint64_t texture_mem_cache = 0;
+ uint64_t buffer_mem_cache = 0;
+ uint64_t total_mem_cache = 0;
+
+public:
+ static Utilities *get_singleton() { return singleton; }
+
+ Utilities();
+ virtual ~Utilities() override;
+
+ /* INSTANCES */
+
+ virtual RS::InstanceType get_base_type(RID p_rid) const override;
+ virtual bool free(RID p_rid) override;
+
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
+ /* VISIBILITY NOTIFIER */
+
+ VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); };
+ bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); };
+
+ virtual RID visibility_notifier_allocate() override;
+ virtual void visibility_notifier_initialize(RID p_notifier) override;
+ virtual void visibility_notifier_free(RID p_notifier) override;
+
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
+
+ /* TIMING */
+
+ virtual void capture_timestamps_begin() override;
+ virtual void capture_timestamp(const String &p_name) override;
+ virtual uint32_t get_captured_timestamps_count() const override;
+ virtual uint64_t get_captured_timestamps_frame() const override;
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override;
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override;
+ virtual String get_captured_timestamp_name(uint32_t p_index) const override;
+
+ /* MISC */
+
+ virtual void update_dirty_resources() override;
+ virtual void set_debug_generate_wireframes(bool p_generate) override {}
+
+ virtual bool has_os_feature(const String &p_feature) const override;
+
+ virtual void update_memory_info() override;
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override;
+
+ virtual String get_video_adapter_name() const override;
+ virtual String get_video_adapter_vendor() const override;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
+ virtual String get_video_adapter_api_version() const override;
+};
+
+} // namespace RendererRD
+
+#endif // !UTILITIES_RD_H
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 325907ee85..aaf7ab8efd 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -470,7 +470,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);
} else {
- RSG::storage->free(p_instance->mesh_instance);
+ RSG::mesh_storage->mesh_free(p_instance->mesh_instance);
p_instance->mesh_instance = RID();
}
@@ -506,7 +506,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->free(instance->mesh_instance);
+ RSG::mesh_storage->mesh_free(instance->mesh_instance);
instance->mesh_instance = RID();
// no need to set instance data flag here, as it was freed above
}
@@ -538,7 +538,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
- RSG::storage->free(collision->instance);
+ RSG::utilities->free(collision->instance);
} break;
case RS::INSTANCE_FOG_VOLUME: {
InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
@@ -607,7 +607,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base = RID();
if (p_base.is_valid()) {
- instance->base_type = RSG::storage->get_base_type(p_base);
+ instance->base_type = RSG::utilities->get_base_type(p_base);
// fix up a specific malfunctioning case before the switch, so it can be handled
if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) {
@@ -724,7 +724,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
- RSG::storage->base_update_dependency(p_base, &instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_base, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -1876,10 +1876,10 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
} break;
case RenderingServer::INSTANCE_FOG_VOLUME: {
- new_aabb = RSG::storage->fog_volume_get_aabb(p_instance->base);
+ new_aabb = RSG::fog->fog_volume_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
- new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
+ new_aabb = RSG::utilities->visibility_notifier_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHT: {
new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);
@@ -3677,7 +3677,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
p_instance->dependency_tracker.update_begin();
if (p_instance->base.is_valid()) {
- RSG::storage->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
}
if (p_instance->material_override.is_valid()) {
@@ -3785,7 +3785,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
- RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(mesh, &p_instance->dependency_tracker);
}
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3885,7 +3885,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
void RendererSceneCull::update_dirty_instances() {
- RSG::storage->update_dirty_resources();
+ RSG::utilities->update_dirty_resources();
while (_instance_update_list.first()) {
_update_dirty_instance(_instance_update_list.first()->self());
@@ -3978,12 +3978,12 @@ void RendererSceneCull::update_visibility_notifiers() {
if (visibility_notifier->just_visible) {
visibility_notifier->just_visible = false;
- RSG::storage->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
+ RSG::utilities->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
} else {
if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
visible_notifier_list.remove(E);
- RSG::storage->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
+ RSG::utilities->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
}
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 4880221586..198898141e 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -42,7 +42,7 @@
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_occlusion_cull.h"
#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "servers/xr/xr_interface.h"
class RendererSceneCull : public RendererScene {
@@ -470,32 +470,32 @@ public:
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
- RendererStorage::DependencyTracker dependency_tracker;
+ DependencyTracker dependency_tracker;
- static void dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *tracker) {
+ static void dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *tracker) {
Instance *instance = (Instance *)tracker->userdata;
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA:
- case RendererStorage::DEPENDENCY_CHANGED_AABB: {
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA:
+ case Dependency::DEPENDENCY_CHANGED_AABB: {
singleton->_instance_queue_update(instance, true, false);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: {
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL: {
singleton->_instance_queue_update(instance, false, true);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_DECAL:
- case RendererStorage::DEPENDENCY_CHANGED_LIGHT:
- case RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_DECAL:
+ case Dependency::DEPENDENCY_CHANGED_LIGHT:
+ case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
singleton->_instance_queue_update(instance, true, true);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES: {
//ignored
} break;
- case RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
+ case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
//requires repairing
if (instance->indexer_id.is_valid()) {
singleton->_unpair_instance(instance);
@@ -506,7 +506,7 @@ public:
}
}
- static void dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *tracker) {
+ static void dependency_deleted(const RID &p_dependency, DependencyTracker *tracker) {
Instance *instance = (Instance *)tracker->userdata;
if (p_dependency == instance->base) {
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index ab9ee2067f..2fccb1fd38 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -175,7 +175,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
- RSG::storage->capture_timestamp(rt_id);
+ RSG::utilities->capture_timestamp(rt_id);
timestamp_vp_map[rt_id] = p_viewport->self;
}
@@ -212,7 +212,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_configure_3d_render_buffers(p_viewport);
}
- Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::storage->get_default_clear_color();
+ Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::texture_storage->get_default_clear_color();
if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -521,7 +521,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_end_" + itos(p_viewport->self.get_id());
- RSG::storage->capture_timestamp(rt_id);
+ RSG::utilities->capture_timestamp(rt_id);
timestamp_vp_map[rt_id] = p_viewport->self;
}
}
@@ -1259,7 +1259,7 @@ void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time,
}
void RendererViewport::set_default_clear_color(const Color &p_color) {
- RSG::storage->set_default_clear_color(p_color);
+ RSG::texture_storage->set_default_clear_color(p_color);
}
// Workaround for setting this on thread.
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 7e035bae80..bcd7e6a1dd 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -48,7 +48,7 @@ void RenderingServerDefault::_free(RID p_rid) {
if (unlikely(p_rid.is_null())) {
return;
}
- if (RSG::storage->free(p_rid)) {
+ if (RSG::utilities->free(p_rid)) {
return;
}
if (RSG::canvas->free(p_rid)) {
@@ -116,35 +116,35 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
RS::get_singleton()->emit_signal(SNAME("frame_post_draw"));
- if (RSG::storage->get_captured_timestamps_count()) {
+ if (RSG::utilities->get_captured_timestamps_count()) {
Vector<FrameProfileArea> new_profile;
- if (RSG::storage->capturing_timestamps) {
- new_profile.resize(RSG::storage->get_captured_timestamps_count());
+ if (RSG::utilities->capturing_timestamps) {
+ new_profile.resize(RSG::utilities->get_captured_timestamps_count());
}
- uint64_t base_cpu = RSG::storage->get_captured_timestamp_cpu_time(0);
- uint64_t base_gpu = RSG::storage->get_captured_timestamp_gpu_time(0);
- for (uint32_t i = 0; i < RSG::storage->get_captured_timestamps_count(); i++) {
- uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i);
- uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i);
+ uint64_t base_cpu = RSG::utilities->get_captured_timestamp_cpu_time(0);
+ uint64_t base_gpu = RSG::utilities->get_captured_timestamp_gpu_time(0);
+ for (uint32_t i = 0; i < RSG::utilities->get_captured_timestamps_count(); i++) {
+ uint64_t time_cpu = RSG::utilities->get_captured_timestamp_cpu_time(i);
+ uint64_t time_gpu = RSG::utilities->get_captured_timestamp_gpu_time(i);
- String name = RSG::storage->get_captured_timestamp_name(i);
+ String name = RSG::utilities->get_captured_timestamp_name(i);
if (name.begins_with("vp_")) {
RSG::viewport->handle_timestamp(name, time_cpu, time_gpu);
}
- if (RSG::storage->capturing_timestamps) {
+ if (RSG::utilities->capturing_timestamps) {
new_profile.write[i].gpu_msec = double((time_gpu - base_gpu) / 1000) / 1000.0;
new_profile.write[i].cpu_msec = double(time_cpu - base_cpu) / 1000.0;
- new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
+ new_profile.write[i].name = RSG::utilities->get_captured_timestamp_name(i);
}
}
frame_profile = new_profile;
}
- frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
+ frame_profile_frame = RSG::utilities->get_captured_timestamps_frame();
if (print_gpu_profile) {
if (print_frame_profile_ticks_from == 0) {
@@ -191,7 +191,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
}
- RSG::storage->update_memory_info();
+ RSG::utilities->update_memory_info();
}
double RenderingServerDefault::get_frame_setup_time_cpu() const {
@@ -250,27 +250,27 @@ uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) {
} else if (p_info == RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME) {
return RSG::viewport->get_total_draw_calls_used();
}
- return RSG::storage->get_rendering_info(p_info);
+ return RSG::utilities->get_rendering_info(p_info);
}
String RenderingServerDefault::get_video_adapter_name() const {
- return RSG::storage->get_video_adapter_name();
+ return RSG::utilities->get_video_adapter_name();
}
String RenderingServerDefault::get_video_adapter_vendor() const {
- return RSG::storage->get_video_adapter_vendor();
+ return RSG::utilities->get_video_adapter_vendor();
}
RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
- return RSG::storage->get_video_adapter_type();
+ return RSG::utilities->get_video_adapter_type();
}
String RenderingServerDefault::get_video_adapter_api_version() const {
- return RSG::storage->get_video_adapter_api_version();
+ return RSG::utilities->get_video_adapter_api_version();
}
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
- RSG::storage->capturing_timestamps = p_enable;
+ RSG::utilities->capturing_timestamps = p_enable;
}
uint64_t RenderingServerDefault::get_frame_profile_frame() {
@@ -301,7 +301,7 @@ void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_posit
}
void RenderingServerDefault::set_print_gpu_profile(bool p_enable) {
- RSG::storage->capturing_timestamps = p_enable;
+ RSG::utilities->capturing_timestamps = p_enable;
print_gpu_profile = p_enable;
}
@@ -313,15 +313,15 @@ RID RenderingServerDefault::get_test_cube() {
}
bool RenderingServerDefault::has_os_feature(const String &p_feature) const {
- if (RSG::storage) {
- return RSG::storage->has_os_feature(p_feature);
+ if (RSG::utilities) {
+ return RSG::utilities->has_os_feature(p_feature);
} else {
return false;
}
}
void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
- RSG::storage->set_debug_generate_wireframes(p_generate);
+ RSG::utilities->set_debug_generate_wireframes(p_generate);
}
bool RenderingServerDefault::is_low_end() const {
@@ -399,13 +399,14 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RendererSceneCull *sr = memnew(RendererSceneCull);
RSG::scene = sr;
RSG::rasterizer = RendererCompositor::create();
+ RSG::utilities = RSG::rasterizer->get_utilities();
RSG::light_storage = RSG::rasterizer->get_light_storage();
RSG::material_storage = RSG::rasterizer->get_material_storage();
RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
RSG::particles_storage = RSG::rasterizer->get_particles_storage();
RSG::texture_storage = RSG::rasterizer->get_texture_storage();
RSG::gi = RSG::rasterizer->get_gi();
- RSG::storage = RSG::rasterizer->get_storage();
+ RSG::fog = RSG::rasterizer->get_fog();
RSG::canvas_render = RSG::rasterizer->get_canvas();
sr->set_scene_render(RSG::rasterizer->get_scene());
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index aef89619db..584d9a7a51 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -31,7 +31,6 @@
#ifndef RENDERING_SERVER_DEFAULT_H
#define RENDERING_SERVER_DEFAULT_H
-#include "core/math/octree.h"
#include "core/templates/command_queue_mt.h"
#include "core/templates/hash_map.h"
#include "renderer_canvas_cull.h"
@@ -524,8 +523,8 @@ public:
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererFog
+#define server_name RSG::fog
FUNCRIDSPLIT(fog_volume)
@@ -535,6 +534,12 @@ public:
/* VISIBILITY_NOTIFIER */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererUtilities
+#define server_name RSG::utilities
+
FUNCRIDSPLIT(visibility_notifier)
FUNC2(visibility_notifier_set_aabb, RID, const AABB &)
FUNC3(visibility_notifier_set_callbacks, RID, const Callable &, const Callable &)
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 1c2a275265..46fa49e683 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -32,13 +32,14 @@
bool RenderingServerGlobals::threaded = false;
+RendererUtilities *RenderingServerGlobals::utilities = nullptr;
RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;
RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
RendererParticlesStorage *RenderingServerGlobals::particles_storage = nullptr;
RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
RendererGI *RenderingServerGlobals::gi = nullptr;
-RendererStorage *RenderingServerGlobals::storage = nullptr;
+RendererFog *RenderingServerGlobals::fog = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 91712f2a51..87d69984f8 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_GLOBALS_H
#define RENDERING_SERVER_GLOBALS_H
+#include "servers/rendering/environment/renderer_fog.h"
#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_canvas_cull.h"
#include "servers/rendering/renderer_canvas_render.h"
@@ -40,6 +41,7 @@
#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
class RendererCanvasCull;
class RendererViewport;
@@ -49,13 +51,14 @@ class RenderingServerGlobals {
public:
static bool threaded;
+ static RendererUtilities *utilities;
static RendererLightStorage *light_storage;
static RendererMaterialStorage *material_storage;
static RendererMeshStorage *mesh_storage;
static RendererParticlesStorage *particles_storage;
static RendererTextureStorage *texture_storage;
static RendererGI *gi;
- static RendererStorage *storage;
+ static RendererFog *fog;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 0cb0f35570..f627e46e52 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -31,7 +31,6 @@
#ifndef LIGHT_STORAGE_H
#define LIGHT_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
class RendererLightStorage {
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index f0363f129a..00790106af 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -31,8 +31,8 @@
#ifndef MATERIAL_STORAGE_H
#define MATERIAL_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+#include "utilities.h"
class RendererMaterialStorage {
public:
@@ -95,7 +95,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
};
#endif // !MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
index 1dac51319c..146f6fde40 100644
--- a/servers/rendering/storage/mesh_storage.h
+++ b/servers/rendering/storage/mesh_storage.h
@@ -31,8 +31,8 @@
#ifndef MESH_STORAGE_H
#define MESH_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+#include "utilities.h"
class RendererMeshStorage {
public:
@@ -130,7 +130,7 @@ public:
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
- virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0;
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
};
#endif // !MESH_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index 268b5473e2..eba68210a5 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -31,7 +31,6 @@
#ifndef PARTICLES_STORAGE_H
#define PARTICLES_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
class RendererParticlesStorage {
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index e3a969d032..e90a028713 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -34,7 +34,18 @@
#include "servers/rendering_server.h"
class RendererTextureStorage {
+private:
+ Color default_clear_color;
+
public:
+ void set_default_clear_color(const Color &p_color) {
+ default_clear_color = p_color;
+ }
+
+ Color get_default_clear_color() const {
+ return default_clear_color;
+ }
+
/* Canvas Texture API */
virtual RID canvas_texture_allocate() = 0;
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/storage/utilities.cpp
index 56409ae187..7cc6417a25 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/storage/utilities.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_storage.cpp */
+/* utilities.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_storage.h"
+#include "utilities.h"
-RendererStorage *RendererStorage::base_singleton = nullptr;
-
-void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) {
+void Dependency::changed_notify(DependencyChangedNotification p_notification) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->changed_callback) {
E.key->changed_callback(p_notification, E.key);
@@ -40,7 +38,7 @@ void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p
}
}
-void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
+void Dependency::deleted_notify(const RID &p_rid) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->deleted_callback) {
E.key->deleted_callback(p_rid, E.key);
@@ -52,7 +50,7 @@ void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
instances.clear();
}
-RendererStorage::Dependency::~Dependency() {
+Dependency::~Dependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
@@ -62,7 +60,3 @@ RendererStorage::Dependency::~Dependency() {
}
#endif
}
-
-RendererStorage::RendererStorage() {
- base_singleton = this;
-}
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/storage/utilities.h
index 859950673e..4d7c34383c 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/storage/utilities.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_storage.h */
+/* utilities.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSTORAGE_H
-#define RENDERINGSERVERSTORAGE_H
+#ifndef RENDERER_UTILITIES_H
+#define RENDERER_UTILITIES_H
#include "servers/rendering_server.h"
-class RendererStorage {
- Color default_clear_color;
+class DependencyTracker;
+class Dependency {
public:
enum DependencyChangedNotification {
DEPENDENCY_CHANGED_AABB,
@@ -52,137 +52,113 @@ public:
DEPENDENCY_CHANGED_REFLECTION_PROBE,
};
- struct DependencyTracker;
+ void changed_notify(DependencyChangedNotification p_notification);
+ void deleted_notify(const RID &p_rid);
- struct Dependency {
- void changed_notify(DependencyChangedNotification p_notification);
- void deleted_notify(const RID &p_rid);
+ ~Dependency();
- ~Dependency();
-
- private:
- friend struct DependencyTracker;
- HashMap<DependencyTracker *, uint32_t> instances;
- };
+private:
+ friend class DependencyTracker;
+ HashMap<DependencyTracker *, uint32_t> instances;
+};
- struct DependencyTracker {
- void *userdata = nullptr;
- typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
- typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
+class DependencyTracker {
+public:
+ void *userdata = nullptr;
+ typedef void (*ChangedCallback)(Dependency::DependencyChangedNotification, DependencyTracker *);
+ typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
- ChangedCallback changed_callback = nullptr;
- DeletedCallback deleted_callback = nullptr;
+ ChangedCallback changed_callback = nullptr;
+ DeletedCallback deleted_callback = nullptr;
- void update_begin() { // call before updating dependencies
- instance_version++;
- }
+ void update_begin() { // call before updating dependencies
+ instance_version++;
+ }
- void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
- dependencies.insert(p_dependency);
- p_dependency->instances[this] = instance_version;
- }
+ void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
+ dependencies.insert(p_dependency);
+ p_dependency->instances[this] = instance_version;
+ }
- void update_end() { //call after updating dependencies
- List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
-
- for (Dependency *E : dependencies) {
- Dependency *dep = E;
- HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
- ERR_CONTINUE(!F);
- if (F->value != instance_version) {
- Pair<Dependency *, DependencyTracker *> p;
- p.first = dep;
- p.second = F->key;
- to_clean_up.push_back(p);
- }
+ void update_end() { //call after updating dependencies
+ List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
+
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
+ HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
+ ERR_CONTINUE(!F);
+ if (F->value != instance_version) {
+ Pair<Dependency *, DependencyTracker *> p;
+ p.first = dep;
+ p.second = F->key;
+ to_clean_up.push_back(p);
}
+ }
- while (to_clean_up.size()) {
- to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
- dependencies.erase(to_clean_up.front()->get().first);
- to_clean_up.pop_front();
- }
+ while (to_clean_up.size()) {
+ to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
+ dependencies.erase(to_clean_up.front()->get().first);
+ to_clean_up.pop_front();
}
+ }
- void clear() { // clear all dependencies
- for (Dependency *E : dependencies) {
- Dependency *dep = E;
- dep->instances.erase(this);
- }
- dependencies.clear();
+ void clear() { // clear all dependencies
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
+ dep->instances.erase(this);
}
+ dependencies.clear();
+ }
- ~DependencyTracker() { clear(); }
+ ~DependencyTracker() { clear(); }
- private:
- friend struct Dependency;
- uint32_t instance_version = 0;
- HashSet<Dependency *> dependencies;
- };
+private:
+ friend class Dependency;
+ uint32_t instance_version = 0;
+ HashSet<Dependency *> dependencies;
+};
- virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
+class RendererUtilities {
+public:
+ virtual ~RendererUtilities() {}
- /* FOG VOLUMES */
+ /* INSTANCES */
- virtual RID fog_volume_allocate() = 0;
- virtual void fog_volume_initialize(RID p_rid) = 0;
+ virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
+ virtual bool free(RID p_rid) = 0;
- virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
- virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
- virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
- virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
- virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* VISIBILITY NOTIFIER */
virtual RID visibility_notifier_allocate() = 0;
virtual void visibility_notifier_initialize(RID p_notifier) = 0;
+ virtual void visibility_notifier_free(RID p_notifier) = 0;
+
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
- virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
- virtual bool free(RID p_rid) = 0;
-
- virtual bool has_os_feature(const String &p_feature) const = 0;
+ /* TIMING */
- virtual void update_dirty_resources() = 0;
-
- virtual void set_debug_generate_wireframes(bool p_generate) = 0;
-
- virtual void update_memory_info() = 0;
-
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
- virtual String get_video_adapter_name() const = 0;
- virtual String get_video_adapter_vendor() const = 0;
- virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
- virtual String get_video_adapter_api_version() const = 0;
-
- static RendererStorage *base_singleton;
-
- void set_default_clear_color(const Color &p_color) {
- default_clear_color = p_color;
- }
+ bool capturing_timestamps = false;
- Color get_default_clear_color() const {
- return default_clear_color;
- }
-#define TIMESTAMP_BEGIN() \
- { \
- if (RSG::storage->capturing_timestamps) \
- RSG::storage->capture_timestamps_begin(); \
+#define TIMESTAMP_BEGIN() \
+ { \
+ if (RSG::utilities->capturing_timestamps) \
+ RSG::utilities->capture_timestamps_begin(); \
}
-#define RENDER_TIMESTAMP(m_text) \
- { \
- if (RSG::storage->capturing_timestamps) \
- RSG::storage->capture_timestamp(m_text); \
+#define RENDER_TIMESTAMP(m_text) \
+ { \
+ if (RSG::utilities->capturing_timestamps) \
+ RSG::utilities->capture_timestamp(m_text); \
}
- bool capturing_timestamps = false;
-
virtual void capture_timestamps_begin() = 0;
virtual void capture_timestamp(const String &p_name) = 0;
virtual uint32_t get_captured_timestamps_count() const = 0;
@@ -191,8 +167,20 @@ public:
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0;
virtual String get_captured_timestamp_name(uint32_t p_index) const = 0;
- RendererStorage();
- virtual ~RendererStorage() {}
+ /* MISC */
+
+ virtual void update_dirty_resources() = 0;
+ virtual void set_debug_generate_wireframes(bool p_generate) = 0;
+
+ virtual bool has_os_feature(const String &p_feature) const = 0;
+
+ virtual void update_memory_info() = 0;
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
+ virtual String get_video_adapter_name() const = 0;
+ virtual String get_video_adapter_vendor() const = 0;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
+ virtual String get_video_adapter_api_version() const = 0;
};
-#endif // RENDERINGSERVERSTORAGE_H
+#endif // !RENDERER_UTILITIES_H
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index e9a558ac5f..68959819c9 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -127,9 +127,6 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_set_scale, "font_rid", "size", "scale");
GDVIRTUAL_BIND(font_get_scale, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_spacing, "font_rid", "size", "spacing", "value");
- GDVIRTUAL_BIND(font_get_spacing, "font_rid", "size", "spacing");
-
GDVIRTUAL_BIND(font_get_texture_count, "font_rid", "size");
GDVIRTUAL_BIND(font_clear_textures, "font_rid", "size");
GDVIRTUAL_BIND(font_remove_texture, "font_rid", "size", "texture_index");
@@ -230,6 +227,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(shaped_text_set_preserve_control, "shaped", "enabled");
GDVIRTUAL_BIND(shaped_text_get_preserve_control, "shaped");
+ GDVIRTUAL_BIND(shaped_text_set_spacing, "shaped", "spacing", "value");
+ GDVIRTUAL_BIND(shaped_text_get_spacing, "shaped", "spacing");
+
GDVIRTUAL_BIND(shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta");
GDVIRTUAL_BIND(shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
GDVIRTUAL_BIND(shaped_text_resize_object, "shaped", "key", "size", "inline_align");
@@ -706,18 +706,6 @@ double TextServerExtension::font_get_scale(const RID &p_font_rid, int64_t p_size
return 0.0;
}
-void TextServerExtension::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) {
- GDVIRTUAL_CALL(font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
-}
-
-int64_t TextServerExtension::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
- return ret;
- }
- return 0;
-}
-
int64_t TextServerExtension::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
int64_t ret;
if (GDVIRTUAL_CALL(font_get_texture_count, p_font_rid, p_size, ret)) {
@@ -1132,6 +1120,18 @@ bool TextServerExtension::shaped_text_get_preserve_control(const RID &p_shaped)
return false;
}
+void TextServerExtension::shaped_text_set_spacing(const RID &p_shaped, TextServer::SpacingType p_spacing, int64_t p_value) {
+ GDVIRTUAL_CALL(shaped_text_set_spacing, p_shaped, p_spacing, p_value);
+}
+
+int64_t TextServerExtension::shaped_text_get_spacing(const RID &p_shaped, TextServer::SpacingType p_spacing) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(shaped_text_get_spacing, p_shaped, p_spacing, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
bool ret;
if (GDVIRTUAL_CALL(shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret)) {
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 9ca0939247..d948a97c66 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -204,11 +204,6 @@ public:
GDVIRTUAL3(font_set_scale, RID, int64_t, double);
GDVIRTUAL2RC(double, font_get_scale, RID, int64_t);
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
- GDVIRTUAL4(font_set_spacing, RID, int64_t, SpacingType, int64_t);
- GDVIRTUAL3RC(int64_t, font_get_spacing, RID, int64_t, SpacingType);
-
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
@@ -377,6 +372,11 @@ public:
GDVIRTUAL2(shaped_text_set_preserve_control, RID, bool);
GDVIRTUAL1RC(bool, shaped_text_get_preserve_control, RID);
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
+ GDVIRTUAL3(shaped_text_set_spacing, RID, SpacingType, int64_t);
+ GDVIRTUAL2RC(int64_t, shaped_text_get_spacing, RID, SpacingType);
+
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index fe5ade88a1..c1293230d8 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -280,9 +280,6 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_scale", "font_rid", "size", "scale"), &TextServer::font_set_scale);
ClassDB::bind_method(D_METHOD("font_get_scale", "font_rid", "size"), &TextServer::font_get_scale);
- ClassDB::bind_method(D_METHOD("font_set_spacing", "font_rid", "size", "spacing", "value"), &TextServer::font_set_spacing);
- ClassDB::bind_method(D_METHOD("font_get_spacing", "font_rid", "size", "spacing"), &TextServer::font_get_spacing);
-
ClassDB::bind_method(D_METHOD("font_get_texture_count", "font_rid", "size"), &TextServer::font_get_texture_count);
ClassDB::bind_method(D_METHOD("font_clear_textures", "font_rid", "size"), &TextServer::font_clear_textures);
ClassDB::bind_method(D_METHOD("font_remove_texture", "font_rid", "size", "texture_index"), &TextServer::font_remove_texture);
@@ -383,6 +380,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_preserve_control", "shaped", "enabled"), &TextServer::shaped_text_set_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_spacing", "shaped", "spacing", "value"), &TextServer::shaped_text_set_spacing);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_spacing", "shaped", "spacing"), &TextServer::shaped_text_get_spacing);
+
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
diff --git a/servers/text_server.h b/servers/text_server.h
index 6339dde0ea..0fd35f2ec0 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -161,6 +161,7 @@ public:
SPACING_SPACE,
SPACING_TOP,
SPACING_BOTTOM,
+ SPACING_MAX,
};
enum FontStyle {
@@ -284,9 +285,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) = 0;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) = 0;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const = 0;
-
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const = 0;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) = 0;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) = 0;
@@ -386,6 +384,9 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) = 0;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const = 0;
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) = 0;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const = 0;
+
virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) = 0;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0;
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index a0bec0f95b..1f3d07c357 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -29,9 +29,7 @@
/*************************************************************************/
#include "xr_interface_extension.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/rendering_server_globals.h"
void XRInterfaceExtension::_bind_methods() {
diff --git a/tests/core/math/test_plane.h b/tests/core/math/test_plane.h
new file mode 100644
index 0000000000..d81a5af1ce
--- /dev/null
+++ b/tests/core/math/test_plane.h
@@ -0,0 +1,172 @@
+/*************************************************************************/
+/* test_plane.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef TEST_PLANE_H
+#define TEST_PLANE_H
+
+#include "core/math/plane.h"
+
+#include "thirdparty/doctest/doctest.h"
+
+namespace TestPlane {
+
+// Plane
+
+TEST_CASE("[Plane] Constructor methods") {
+ const Plane plane = Plane(32, 22, 16, 3);
+ const Plane plane_vector = Plane(Vector3(32, 22, 16), 3);
+ const Plane plane_copy_plane = Plane(plane);
+
+ CHECK_MESSAGE(
+ plane == plane_vector,
+ "Planes created with same values but different methods should be equal.");
+
+ CHECK_MESSAGE(
+ plane == plane_copy_plane,
+ "Planes created with same values but different methods should be equal.");
+}
+
+TEST_CASE("[Plane] Basic getters") {
+ const Plane plane = Plane(32, 22, 16, 3);
+ const Plane plane_normalized = Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42);
+
+ CHECK_MESSAGE(
+ plane.get_normal().is_equal_approx(Vector3(32, 22, 16)),
+ "get_normal() should return the expected value.");
+
+ CHECK_MESSAGE(
+ plane.normalized().is_equal_approx(plane_normalized),
+ "normalized() should return a copy of the normalized value.");
+}
+
+TEST_CASE("[Plane] Basic setters") {
+ Plane plane = Plane(32, 22, 16, 3);
+ plane.set_normal(Vector3(4, 2, 3));
+
+ CHECK_MESSAGE(
+ plane.is_equal_approx(Plane(4, 2, 3, 3)),
+ "set_normal() should result in the expected plane.");
+
+ plane = Plane(32, 22, 16, 3);
+ plane.normalize();
+
+ CHECK_MESSAGE(
+ plane.is_equal_approx(Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42)),
+ "normalize() should result in the expected plane.");
+}
+
+TEST_CASE("[Plane] Plane-point operations") {
+ const Plane plane = Plane(32, 22, 16, 3);
+ const Plane y_facing_plane = Plane(0, 1, 0, 4);
+
+ CHECK_MESSAGE(
+ plane.center().is_equal_approx(Vector3(32 * 3, 22 * 3, 16 * 3)),
+ "center() should return a vector pointing to the center of the plane.");
+
+ CHECK_MESSAGE(
+ y_facing_plane.is_point_over(Vector3(0, 5, 0)),
+ "is_point_over() should return the expected result.");
+
+ CHECK_MESSAGE(
+ y_facing_plane.get_any_perpendicular_normal().is_equal_approx(Vector3(1, 0, 0)),
+ "get_any_perpindicular_normal() should return the expected result.");
+
+ // TODO distance_to()
+}
+
+TEST_CASE("[Plane] Has point") {
+ const Plane x_facing_plane = Plane(1, 0, 0, 0);
+ const Plane y_facing_plane = Plane(0, 1, 0, 0);
+ const Plane z_facing_plane = Plane(0, 0, 1, 0);
+
+ const Vector3 x_axis_point = Vector3(10, 0, 0);
+ const Vector3 y_axis_point = Vector3(0, 10, 0);
+ const Vector3 z_axis_point = Vector3(0, 0, 10);
+
+ const Plane x_facing_plane_with_d_offset = Plane(1, 0, 0, 1);
+ const Vector3 y_axis_point_with_d_offset = Vector3(1, 10, 0);
+
+ CHECK_MESSAGE(
+ x_facing_plane.has_point(y_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+ CHECK_MESSAGE(
+ x_facing_plane.has_point(z_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+
+ CHECK_MESSAGE(
+ y_facing_plane.has_point(x_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+ CHECK_MESSAGE(
+ y_facing_plane.has_point(z_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+
+ CHECK_MESSAGE(
+ z_facing_plane.has_point(y_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+ CHECK_MESSAGE(
+ z_facing_plane.has_point(x_axis_point),
+ "has_point() with contained Vector3 should return the expected result.");
+
+ CHECK_MESSAGE(
+ x_facing_plane_with_d_offset.has_point(y_axis_point_with_d_offset),
+ "has_point() with passed Vector3 should return the expected result.");
+}
+
+TEST_CASE("[Plane] Intersection") {
+ const Plane x_facing_plane = Plane(1, 0, 0, 1);
+ const Plane y_facing_plane = Plane(0, 1, 0, 2);
+ const Plane z_facing_plane = Plane(0, 0, 1, 3);
+
+ Vector3 vec_out;
+
+ CHECK_MESSAGE(
+ x_facing_plane.intersect_3(y_facing_plane, z_facing_plane, &vec_out),
+ "intersect_3() should return the expected result.");
+ CHECK_MESSAGE(
+ vec_out.is_equal_approx(Vector3(1, 2, 3)),
+ "intersect_3() should modify vec_out to the expected result.");
+
+ CHECK_MESSAGE(
+ x_facing_plane.intersects_ray(Vector3(0, 1, 1), Vector3(2, 0, 0), &vec_out),
+ "intersects_ray() should return the expected result.");
+ CHECK_MESSAGE(
+ vec_out.is_equal_approx(Vector3(1, 1, 1)),
+ "intersects_ray() should modify vec_out to the expected result.");
+
+ CHECK_MESSAGE(
+ x_facing_plane.intersects_segment(Vector3(0, 1, 1), Vector3(2, 1, 1), &vec_out),
+ "intersects_segment() should return the expected result.");
+ CHECK_MESSAGE(
+ vec_out.is_equal_approx(Vector3(1, 1, 1)),
+ "intersects_segment() should modify vec_out to the expected result.");
+}
+} // namespace TestPlane
+
+#endif // TEST_PLANE_H
diff --git a/tests/core/object/test_class_db.h b/tests/core/object/test_class_db.h
index 7ea9e16ff1..c7535426df 100644
--- a/tests/core/object/test_class_db.h
+++ b/tests/core/object/test_class_db.h
@@ -597,7 +597,7 @@ void add_exposed_classes(Context &r_context) {
(exposed_class.name != r_context.names_cache.object_class || String(method.name) != "free"),
warn_msg.utf8().get_data());
- } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ } else if (return_info.type == Variant::INT && return_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
method.return_type.name = return_info.class_name;
method.return_type.is_enum = true;
} else if (return_info.class_name != StringName()) {
@@ -626,7 +626,7 @@ void add_exposed_classes(Context &r_context) {
ArgumentData arg;
arg.name = orig_arg_name;
- if (arg_info.type == Variant::INT && arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (arg_info.type == Variant::INT && arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
arg.type.name = arg_info.class_name;
arg.type.is_enum = true;
} else if (arg_info.class_name != StringName()) {
@@ -694,7 +694,7 @@ void add_exposed_classes(Context &r_context) {
ArgumentData arg;
arg.name = orig_arg_name;
- if (arg_info.type == Variant::INT && arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ if (arg_info.type == Variant::INT && arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) {
arg.type.name = arg_info.class_name;
arg.type.is_enum = true;
} else if (arg_info.class_name != StringName()) {
@@ -732,13 +732,13 @@ void add_exposed_classes(Context &r_context) {
List<String> constants;
ClassDB::get_integer_constant_list(class_name, &constants, true);
- const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map;
+ const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map;
- for (const KeyValue<StringName, List<StringName>> &K : enum_map) {
+ for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &K : enum_map) {
EnumData enum_;
enum_.name = K.key;
- for (const StringName &E : K.value) {
+ for (const StringName &E : K.value.constants) {
const StringName &constant_name = E;
TEST_FAIL_COND(String(constant_name).find("::") != -1,
"Enum constant contains '::', check bindings to remove the scope: '",
diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h
index 0b191d2d94..0c5704d6c9 100644
--- a/tests/core/string/test_string.h
+++ b/tests/core/string/test_string.h
@@ -89,12 +89,12 @@ TEST_CASE("[String] UTF8") {
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s = u32str;
- bool err = s.parse_utf8(s.utf8().get_data());
- CHECK(!err);
+ Error err = s.parse_utf8(s.utf8().get_data());
+ CHECK(err == OK);
CHECK(s == u32str);
err = s.parse_utf8((const char *)u8str);
- CHECK(!err);
+ CHECK(err == OK);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
@@ -106,12 +106,12 @@ TEST_CASE("[String] UTF16") {
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const char16_t u16str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
String s = u32str;
- bool err = s.parse_utf16(s.utf16().get_data());
- CHECK(!err);
+ Error err = s.parse_utf16(s.utf16().get_data());
+ CHECK(err == OK);
CHECK(s == u32str);
err = s.parse_utf16(u16str);
- CHECK(!err);
+ CHECK(err == OK);
CHECK(s == u32str);
Char16String cs = u16str;
@@ -123,8 +123,8 @@ TEST_CASE("[String] UTF8 with BOM") {
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s;
- bool err = s.parse_utf8((const char *)u8str);
- CHECK(!err);
+ Error err = s.parse_utf8((const char *)u8str);
+ CHECK(err == OK);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
@@ -137,12 +137,12 @@ TEST_CASE("[String] UTF16 with BOM") {
static const char16_t u16str[] = { 0xFEFF, 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
static const char16_t u16str_swap[] = { 0xFFFE, 0x2000, 0x4500, 0x4A30, 0x0F36, 0x8830, 0x4630, 0x3CD8, 0xA4DF, 0 };
String s;
- bool err = s.parse_utf16(u16str);
- CHECK(!err);
+ Error err = s.parse_utf16(u16str);
+ CHECK(err == OK);
CHECK(s == u32str);
err = s.parse_utf16(u16str_swap);
- CHECK(!err);
+ CHECK(err == OK);
CHECK(s == u32str);
Char16String cs = u16str;
@@ -152,29 +152,48 @@ TEST_CASE("[String] UTF16 with BOM") {
CHECK(String::utf16(cs) == s);
}
-TEST_CASE("[String] Invalid UTF8") {
+TEST_CASE("[String] Invalid UTF8 (non-standard)") {
ERR_PRINT_OFF
- static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
+ static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 };
+ // + +2 +2 +2 +3 overlong +3 unpaired +2
+ static const char32_t u32str[] = { 0x45, 0x304A, 0x3088, 0x3046, 0x1F3A4, 0x20AC, 0xD801, 0 };
String s;
- bool err = s.parse_utf8((const char *)u8str);
- CHECK(err);
- CHECK(s.is_empty());
+ Error err = s.parse_utf8((const char *)u8str);
+ CHECK(err == ERR_PARSE_ERROR);
+ CHECK(s == u32str);
CharString cs = (const char *)u8str;
- CHECK(String::utf8(cs).is_empty());
+ CHECK(String::utf8(cs) == s);
ERR_PRINT_ON
}
-TEST_CASE("[String] Invalid UTF16") {
+TEST_CASE("[String] Invalid UTF8 (unrecoverable)") {
+ ERR_PRINT_OFF
+ static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xC0, 0x80, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 };
+ // + +2 inv +2 inv inv inv +2 +2 ovl NUL +1 +3 overlong +3 unpaired +2
+ static const char32_t u32str[] = { 0x45, 0x304A, 0x20, 0x20, 0x20, 0x20, 0x3088, 0x3046, 0x20, 0x1F3A4, 0x20AC, 0xD801, 0 };
+ String s;
+ Error err = s.parse_utf8((const char *)u8str);
+ CHECK(err == ERR_INVALID_DATA);
+ CHECK(s == u32str);
+
+ CharString cs = (const char *)u8str;
+ CHECK(String::utf8(cs) == s);
+ ERR_PRINT_ON
+}
+
+TEST_CASE("[String] Invalid UTF16 (non-standard)") {
ERR_PRINT_OFF
static const char16_t u16str[] = { 0x0045, 0x304A, 0x3088, 0x3046, 0xDFA4, 0 };
+ // + + + + unpaired
+ static const char32_t u32str[] = { 0x0045, 0x304A, 0x3088, 0x3046, 0xDFA4, 0 };
String s;
- bool err = s.parse_utf16(u16str);
- CHECK(err);
- CHECK(s.is_empty());
+ Error err = s.parse_utf16(u16str);
+ CHECK(err == ERR_PARSE_ERROR);
+ CHECK(s == u32str);
Char16String cs = u16str;
- CHECK(String::utf16(cs).is_empty());
+ CHECK(String::utf16(cs) == s);
ERR_PRINT_ON
}
@@ -262,8 +281,8 @@ TEST_CASE("[String] Test chr") {
CHECK(String::chr('H') == "H");
CHECK(String::chr(0x3012)[0] == 0x3012);
ERR_PRINT_OFF
- CHECK(String::chr(0xd812)[0] == 0xfffd); // Unpaired UTF-16 surrogate
- CHECK(String::chr(0x20d812)[0] == 0xfffd); // Outside UTF-32 range
+ CHECK(String::chr(0xd812)[0] == 0xd812); // Unpaired UTF-16 surrogate
+ CHECK(String::chr(0x20d812)[0] == 0x20d812); // Outside UTF-32 range
ERR_PRINT_ON
}
@@ -1125,9 +1144,9 @@ TEST_CASE("[String] lstrip and rstrip") {
#undef STRIP_TEST
}
-TEST_CASE("[String] ensuring empty string into parse_utf8 passes empty string") {
+TEST_CASE("[String] Ensuring empty string into parse_utf8 passes empty string") {
String empty;
- CHECK(empty.parse_utf8(nullptr, -1));
+ CHECK(empty.parse_utf8(nullptr, -1) == ERR_INVALID_DATA);
}
TEST_CASE("[String] Cyrillic to_lower()") {
@@ -1440,8 +1459,8 @@ TEST_CASE("[String] validate_node_name") {
String name_with_spaces = "Name with spaces";
CHECK(name_with_spaces.validate_node_name() == "Name with spaces");
- String name_with_kana = "Name with kana ゴドツ";
- CHECK(name_with_kana.validate_node_name() == "Name with kana ゴドツ");
+ String name_with_kana = U"Name with kana ゴドツ";
+ CHECK(name_with_kana.validate_node_name() == U"Name with kana ゴドツ");
String name_with_invalid_chars = "Name with invalid characters :.@removed!";
CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters removed!");
diff --git a/tests/scene/test_theme.h b/tests/scene/test_theme.h
index fedffc8449..f7cfa0fd5b 100644
--- a/tests/scene/test_theme.h
+++ b/tests/scene/test_theme.h
@@ -46,7 +46,7 @@ public:
} const valid_data[Theme::DATA_TYPE_MAX] = {
{ Theme::DATA_TYPE_COLOR, Color() },
{ Theme::DATA_TYPE_CONSTANT, 42 },
- { Theme::DATA_TYPE_FONT, Ref<Font>(memnew(Font)) },
+ { Theme::DATA_TYPE_FONT, Ref<FontFile>(memnew(FontFile)) },
{ Theme::DATA_TYPE_FONT_SIZE, 42 },
{ Theme::DATA_TYPE_ICON, Ref<Texture>(memnew(ImageTexture)) },
{ Theme::DATA_TYPE_STYLEBOX, Ref<StyleBox>(memnew(StyleBoxFlat)) },
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index ac0cdf0cc1..79cda7e512 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -45,6 +45,7 @@
#include "tests/core/math/test_expression.h"
#include "tests/core/math/test_geometry_2d.h"
#include "tests/core/math/test_geometry_3d.h"
+#include "tests/core/math/test_plane.h"
#include "tests/core/math/test_random_number_generator.h"
#include "tests/core/math/test_rect2.h"
#include "tests/core/math/test_rect2i.h"
diff --git a/thirdparty/README.md b/thirdparty/README.md
index ed8eb9f48f..94b071a2ea 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -213,7 +213,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 4.3.0 (aee123fc83388b8f5acfb301d87bd92eccc5b843, 2022)
+- Version: 4.4.1 (096aaa62a6e0d07c02a4894fc036efc927e5aaf9, 2022)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS.hh
new file mode 100644
index 0000000000..224d6b746b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS.hh
@@ -0,0 +1,165 @@
+#ifndef OT_LAYOUT_GPOS_HH
+#define OT_LAYOUT_GPOS_HH
+
+#include "../../hb-ot-layout-common.hh"
+#include "../../hb-ot-layout-gsubgpos.hh"
+#include "GPOS/Common.hh"
+#include "GPOS/PosLookup.hh"
+
+namespace OT {
+namespace Layout {
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level = HB_MAX_NESTING_LEVEL);
+
+/*
+ * GPOS -- Glyph Positioning
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
+ */
+
+struct GPOS : GSUBGPOS
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
+
+ using Lookup = GPOS_impl::PosLookup;
+
+ const GPOS_impl::PosLookup& get_lookup (unsigned int i) const
+ { return static_cast<const GPOS_impl::PosLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
+ return GSUBGPOS::subset<GPOS_impl::PosLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return GSUBGPOS::sanitize<GPOS_impl::PosLookup> (c); }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
+ {
+ if (!c->gpos_lookups->has (i)) continue;
+ const GPOS_impl::PosLookup &l = get_lookup (i);
+ l.dispatch (c);
+ }
+ }
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<GPOS_impl::PosLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
+};
+
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level)
+{
+ /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
+ * offset of glyph they are attached to. */
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ if (unlikely (j >= len))
+ return;
+
+ if (unlikely (!nesting_level))
+ return;
+
+ propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
+
+ assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
+
+ if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
+ {
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[i].y_offset += pos[j].y_offset;
+ else
+ pos[i].x_offset += pos[j].x_offset;
+ }
+ else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
+ {
+ pos[i].x_offset += pos[j].x_offset;
+ pos[i].y_offset += pos[j].y_offset;
+
+ assert (j < i);
+ if (HB_DIRECTION_IS_FORWARD (direction))
+ for (unsigned int k = j; k < i; k++) {
+ pos[i].x_offset -= pos[k].x_advance;
+ pos[i].y_offset -= pos[k].y_advance;
+ }
+ else
+ for (unsigned int k = j + 1; k < i + 1; k++) {
+ pos[i].x_offset += pos[k].x_advance;
+ pos[i].y_offset += pos[k].y_advance;
+ }
+ }
+}
+
+void
+GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
+}
+
+void
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
+{
+ //_hb_buffer_assert_gsubgpos_vars (buffer);
+}
+
+void
+GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
+{
+ _hb_buffer_assert_gsubgpos_vars (buffer);
+
+ unsigned int len;
+ hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
+ hb_direction_t direction = buffer->props.direction;
+
+ /* Handle attachments */
+ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
+ for (unsigned i = 0; i < len; i++)
+ propagate_attachment_offsets (pos, len, i, direction);
+
+ if (unlikely (font->slant))
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (unlikely (pos[i].y_offset))
+ pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
+ }
+}
+
+}
+
+struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
+ GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
+};
+
+}
+
+#endif /* OT_LAYOUT_GPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
new file mode 100644
index 0000000000..bfe6b36afd
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
@@ -0,0 +1,84 @@
+#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
+#define OT_LAYOUT_GPOS_ANCHOR_HH
+
+#include "AnchorFormat1.hh"
+#include "AnchorFormat2.hh"
+#include "AnchorFormat3.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct Anchor
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AnchorFormat1 format1;
+ AnchorFormat2 format2;
+ AnchorFormat3 format3;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 1: return_trace (u.format1.sanitize (c));
+ case 2: return_trace (u.format2.sanitize (c));
+ case 3: return_trace (u.format3.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ *x = *y = 0;
+ switch (u.format) {
+ case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
+ case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
+ case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
+ default: return;
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ switch (u.format) {
+ case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ case 2:
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ // AnchorFormat 2 just containins extra hinting information, so
+ // if hints are being dropped convert to format 1.
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ }
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+ case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
+ c->plan->layout_variation_idx_map))));
+ default:return_trace (false);
+ }
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ switch (u.format) {
+ case 1: case 2:
+ return;
+ case 3:
+ u.format3.collect_variation_indices (c);
+ return;
+ default: return;
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHOR_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh
new file mode 100644
index 0000000000..738cc31bbf
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh
@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ public:
+ DEFINE_SIZE_STATIC (6);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat1* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+ if (!out) return_trace (out);
+ out->format = 1;
+ return_trace (out);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh
new file mode 100644
index 0000000000..70b4d19f53
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh
@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat2
+{
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ HBUINT16 anchorPoint; /* Index to glyph contour point */
+ public:
+ DEFINE_SIZE_STATIC (8);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ return;
+#endif
+
+ unsigned int x_ppem = font->x_ppem;
+ unsigned int y_ppem = font->y_ppem;
+ hb_position_t cx = 0, cy = 0;
+ bool ret;
+
+ ret = (x_ppem || y_ppem) &&
+ font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+ *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat2* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed<AnchorFormat2> (this));
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh
new file mode 100644
index 0000000000..d77b4699be
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh
@@ -0,0 +1,70 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat3
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 3 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ Offset16To<Device>
+ xDeviceTable; /* Offset to Device table for X
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ Offset16To<Device>
+ yDeviceTable; /* Offset to Device table for Y
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ public:
+ DEFINE_SIZE_STATIC (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+
+ if (font->x_ppem || font->num_coords)
+ *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
+ if (font->y_ppem || font->num_coords)
+ *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
+ }
+
+ AnchorFormat3* copy (hb_serialize_context_t *c,
+ const hb_map_t *layout_variation_idx_map) const
+ {
+ TRACE_SERIALIZE (this);
+ if (!layout_variation_idx_map) return_trace (nullptr);
+
+ auto *out = c->embed<AnchorFormat3> (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
+ out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
+ (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh
new file mode 100644
index 0000000000..c442efa1ea
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorMatrix
+{
+ HBUINT16 rows; /* Number of rows */
+ UnsizedArrayOf<Offset16To<Anchor>>
+ matrixZ; /* Matrix of offsets to Anchor tables--
+ * from beginning of AnchorMatrix table */
+ public:
+ DEFINE_SIZE_ARRAY (2, matrixZ);
+
+ bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+ {
+ TRACE_SANITIZE (this);
+ if (!c->check_struct (this)) return_trace (false);
+ if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
+ unsigned int count = rows * cols;
+ if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+ for (unsigned int i = 0; i < count; i++)
+ if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+ return_trace (true);
+ }
+
+ const Anchor& get_anchor (unsigned int row, unsigned int col,
+ unsigned int cols, bool *found) const
+ {
+ *found = false;
+ if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
+ *found = !matrixZ[row * cols + col].is_null ();
+ return this+matrixZ[row * cols + col];
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ Iterator index_iter) const
+ {
+ for (unsigned i : index_iter)
+ (this+matrixZ[i]).collect_variation_indices (c);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ unsigned num_rows,
+ Iterator index_iter) const
+ {
+ TRACE_SUBSET (this);
+
+ auto *out = c->serializer->start_embed (this);
+
+ if (!index_iter) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ out->rows = num_rows;
+ for (const unsigned i : index_iter)
+ {
+ auto *offset = c->serializer->embed (matrixZ[i]);
+ if (!offset) return_trace (false);
+ offset->serialize_subset (c, matrixZ[i], this);
+ }
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh
new file mode 100644
index 0000000000..d551ac2a2b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ChainContextPos : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh
new file mode 100644
index 0000000000..e16c06729d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh
@@ -0,0 +1,32 @@
+#ifndef OT_LAYOUT_GPOS_COMMON_HH
+#define OT_LAYOUT_GPOS_COMMON_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+enum attach_type_t {
+ ATTACH_TYPE_NONE = 0X00,
+
+ /* Each attachment should be either a mark or a cursive; can't be both. */
+ ATTACH_TYPE_MARK = 0X01,
+ ATTACH_TYPE_CURSIVE = 0X02,
+};
+
+/* buffer **position** var allocations */
+#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
+#define attach_type() var.u8[2] /* attachment type */
+/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
+
+template<typename Iterator, typename SrcLookup>
+static void SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_map_t *layout_variation_idx_map);
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_COMMON_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh
new file mode 100644
index 0000000000..2a01eaa3a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ContextPos : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh
new file mode 100644
index 0000000000..c105cfb091
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh
@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
+
+#include "CursivePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct CursivePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CursivePosFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh
new file mode 100644
index 0000000000..e212fab976
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -0,0 +1,281 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+
+#include "Anchor.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct EntryExitRecord
+{
+ friend struct CursivePosFormat1;
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+entryAnchor).collect_variation_indices (c);
+ (src_base+exitAnchor).collect_variation_indices (c);
+ }
+
+ EntryExitRecord* subset (hb_subset_context_t *c,
+ const void *src_base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
+ out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
+ return_trace (out);
+ }
+
+ protected:
+ Offset16To<Anchor>
+ entryAnchor; /* Offset to EntryAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ Offset16To<Anchor>
+ exitAnchor; /* Offset to ExitAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+static void
+reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ /* Stop if we see new parent in the chain. */
+ if (j == new_parent)
+ return;
+
+ reverse_cursive_minor_offset (pos, j, direction, new_parent);
+
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[j].y_offset = -pos[i].y_offset;
+ else
+ pos[j].x_offset = -pos[i].x_offset;
+
+ pos[j].attach_chain() = -chain;
+ pos[j].attach_type() = type;
+}
+
+
+struct CursivePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ Array16Of<EntryExitRecord>
+ entryExitRecord; /* Array of EntryExit records--in
+ * Coverage Index order */
+ public:
+ DEFINE_SIZE_ARRAY (6, entryExitRecord);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+
+ const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
+ if (!this_record.entryAnchor) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
+ if (!prev_record.exitAnchor)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int i = skippy_iter.idx;
+ unsigned int j = buffer->idx;
+
+ buffer->unsafe_to_break (i, j);
+ float entry_x, entry_y, exit_x, exit_y;
+ (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+
+ hb_glyph_position_t *pos = buffer->pos;
+
+ hb_position_t d;
+ /* Main-direction adjustment */
+ switch (c->direction) {
+ case HB_DIRECTION_LTR:
+ pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
+
+ d = roundf (entry_x) + pos[j].x_offset;
+ pos[j].x_advance -= d;
+ pos[j].x_offset -= d;
+ break;
+ case HB_DIRECTION_RTL:
+ d = roundf (exit_x) + pos[i].x_offset;
+ pos[i].x_advance -= d;
+ pos[i].x_offset -= d;
+
+ pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
+ break;
+ case HB_DIRECTION_TTB:
+ pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
+
+ d = roundf (entry_y) + pos[j].y_offset;
+ pos[j].y_advance -= d;
+ pos[j].y_offset -= d;
+ break;
+ case HB_DIRECTION_BTT:
+ d = roundf (exit_y) + pos[i].y_offset;
+ pos[i].y_advance -= d;
+ pos[i].y_offset -= d;
+
+ pos[j].y_advance = roundf (entry_y);
+ break;
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
+ }
+
+ /* Cross-direction adjustment */
+
+ /* We attach child to parent (think graph theory and rooted trees whereas
+ * the root stays on baseline and each node aligns itself against its
+ * parent.
+ *
+ * Optimize things for the case of RightToLeft, as that's most common in
+ * Arabic. */
+ unsigned int child = i;
+ unsigned int parent = j;
+ hb_position_t x_offset = entry_x - exit_x;
+ hb_position_t y_offset = entry_y - exit_y;
+ if (!(c->lookup_props & LookupFlag::RightToLeft))
+ {
+ unsigned int k = child;
+ child = parent;
+ parent = k;
+ x_offset = -x_offset;
+ y_offset = -y_offset;
+ }
+
+ /* If child was already connected to someone else, walk through its old
+ * chain and reverse the link direction, such that the whole tree of its
+ * previous connection now attaches to new parent. Watch out for case
+ * where new parent is on the path from old chain...
+ */
+ reverse_cursive_minor_offset (pos, child, c->direction, parent);
+
+ pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[child].attach_chain() = (int) parent - (int) child;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[child].y_offset = y_offset;
+ else
+ pos[child].x_offset = x_offset;
+
+ /* If parent was attached to child, separate them.
+ * https://github.com/harfbuzz/harfbuzz/issues/2469
+ */
+ if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
+ pos[parent].attach_chain() = 0;
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_subset_context_t *c,
+ Iterator it,
+ const void *src_base)
+ {
+ if (unlikely (!c->serializer->extend_min ((*this)))) return;
+ this->format = 1;
+ this->entryExitRecord.len = it.len ();
+
+ for (const EntryExitRecord& entry_record : + it
+ | hb_map (hb_second))
+ entry_record.subset (c, src_base);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c->serializer, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto it =
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
+ { return hb_pair (glyph_map[p.first], p.second);})
+ ;
+
+ bool ret = bool (it);
+ out->serialize (c, it, this);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh
new file mode 100644
index 0000000000..d1808adab4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh
@@ -0,0 +1,17 @@
+#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ExtensionPos : Extension<ExtensionPos>
+{
+ typedef struct PosLookupSubTable SubTable;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
new file mode 100644
index 0000000000..f8cddd1991
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
@@ -0,0 +1,113 @@
+#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
+#define OT_LAYOUT_GPOS_MARKARRAY_HH
+
+#include "AnchorMatrix.hh"
+#include "MarkRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
+{
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (Array16Of<MarkRecord>::sanitize (c, this));
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ unsigned int mark_index, unsigned int glyph_index,
+ const AnchorMatrix &anchors, unsigned int class_count,
+ unsigned int glyph_pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
+ unsigned int mark_class = record.klass;
+
+ const Anchor& mark_anchor = this + record.markAnchor;
+ bool found;
+ const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
+ /* If this subtable doesn't have an anchor for this base and this class,
+ * return false such that the subsequent subtables have a chance at it. */
+ if (unlikely (!found)) return_trace (false);
+
+ float mark_x, mark_y, base_x, base_y;
+
+ buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
+ mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+
+ hb_glyph_position_t &o = buffer->cur_pos();
+ o.x_offset = roundf (base_x - mark_x);
+ o.y_offset = roundf (base_y - mark_y);
+ o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto* out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ auto mark_iter =
+ + hb_zip (coverage, this->iter ())
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ unsigned new_length = 0;
+ for (const auto& mark_record : mark_iter) {
+ if (unlikely (!mark_record.subset (c, this, klass_mapping)))
+ return_trace (false);
+ new_length++;
+ }
+
+ if (unlikely (!c->serializer->check_assign (out->len, new_length,
+ HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
+ return_trace (false);
+
+ return_trace (true);
+ }
+};
+
+static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
+ const MarkArray &mark_array,
+ const hb_set_t &glyphset,
+ hb_map_t* klass_mapping /* INOUT */)
+{
+ hb_set_t orig_classes;
+
+ + hb_zip (mark_coverage, mark_array)
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ | hb_map (&MarkRecord::get_class)
+ | hb_sink (orig_classes)
+ ;
+
+ unsigned idx = 0;
+ for (auto klass : orig_classes.iter ())
+ {
+ if (klass_mapping->has (klass)) continue;
+ klass_mapping->set (klass, idx);
+ idx++;
+ }
+}
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
new file mode 100644
index 0000000000..e99e13ff84
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOS_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOS_HH
+
+#include "MarkBasePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkBasePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkBasePosFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
new file mode 100644
index 0000000000..a10b806fe5
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
@@ -0,0 +1,217 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+
+#include "MarkArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix BaseArray; /* base-major--
+ * in order of BaseCoverage Index--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+struct MarkBasePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ markCoverage; /* Offset to MarkCoverage table--from
+ * beginning of MarkBasePos subtable */
+ Offset16To<Coverage>
+ baseCoverage; /* Offset to BaseCoverage table--from
+ * beginning of MarkBasePos subtable */
+ HBUINT16 classCount; /* Number of classes defined for marks */
+ Offset16To<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkBasePos subtable */
+ Offset16To<BaseArray>
+ baseArray; /* Offset to BaseArray table--from
+ * beginning of MarkBasePos subtable */
+
+ public:
+ DEFINE_SIZE_STATIC (12);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ baseCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ baseArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+baseCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : base_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+ (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return_trace (false);
+
+ /* Now we search backwards for a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
+ do {
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* We only want to attach to the first of a MultipleSubst sequence.
+ * https://github.com/harfbuzz/harfbuzz/issues/740
+ * Reject others...
+ * ...but stop if we find a mark in the MultipleSubst sequence:
+ * https://github.com/harfbuzz/harfbuzz/issues/1020 */
+ if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
+ 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
+ (skippy_iter.idx == 0 ||
+ _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
+ ))
+ break;
+ skippy_iter.reject ();
+ } while (true);
+
+ /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
+ //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+
+ unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
+ if (base_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + base_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : + base_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+
+ out->baseArray.serialize_subset (c, baseArray, this,
+ base_iter.len (),
+ base_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
new file mode 100644
index 0000000000..7e74aa73e0
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOS_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOS_HH
+
+#include "MarkLigPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkLigPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkLigPosFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
new file mode 100644
index 0000000000..4382aa6c6c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
@@ -0,0 +1,244 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix LigatureAttach; /* component-major--
+ * in order of writing direction--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
+struct LigatureArray : List16OfOffset16To<LigatureAttach>
+{
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ unsigned class_count,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ for (const auto _ : + hb_zip (coverage, *this)
+ | hb_filter (glyphset, hb_first))
+ {
+ auto *matrix = out->serialize_append (c->serializer);
+ if (unlikely (!matrix)) return_trace (false);
+
+ const LigatureAttach& src = (this + _.second);
+ auto indexes =
+ + hb_range (src.rows * class_count)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+ ;
+ matrix->serialize_subset (c,
+ _.second,
+ this,
+ src.rows,
+ indexes);
+ }
+ return_trace (this->len);
+ }
+};
+
+struct MarkLigPosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ markCoverage; /* Offset to Mark Coverage table--from
+ * beginning of MarkLigPos subtable */
+ Offset16To<Coverage>
+ ligatureCoverage; /* Offset to Ligature Coverage
+ * table--from beginning of MarkLigPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ Offset16To<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkLigPos subtable */
+ Offset16To<LigatureArray>
+ ligatureArray; /* Offset to LigatureArray table--from
+ * beginning of MarkLigPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (12);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ ligatureCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ ligatureArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+ligatureCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned ligcount = (this+ligatureArray).len;
+ auto lig_iter =
+ + hb_zip (this+ligatureCoverage, hb_range (ligcount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ for (const unsigned i : lig_iter)
+ {
+ hb_sorted_vector_t<unsigned> lig_indexes;
+ unsigned row_count = lig_array[i].rows;
+ for (unsigned row : + hb_range (row_count))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (lig_indexes)
+ ;
+ }
+
+ lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return_trace (false);
+
+ /* Now we search backwards for a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
+ //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+
+ unsigned int j = skippy_iter.idx;
+ unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
+ if (lig_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ const LigatureAttach& lig_attach = lig_array[lig_index];
+
+ /* Find component to attach to */
+ unsigned int comp_count = lig_attach.rows;
+ if (unlikely (!comp_count))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* We must now check whether the ligature ID of the current mark glyph
+ * is identical to the ligature ID of the found ligature. If yes, we
+ * can directly use the component index. If not, we attach the mark
+ * glyph to the last component of the ligature. */
+ unsigned int comp_index;
+ unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ if (lig_id && lig_id == mark_id && mark_comp > 0)
+ comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
+ else
+ comp_index = comp_count - 1;
+
+ return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ auto new_mark_coverage =
+ + mark_iter
+ | hb_map_retains_sorting (hb_first)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ auto new_ligature_coverage =
+ + hb_iter (this + ligatureCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
+ return_trace (false);
+
+ out->ligatureArray.serialize_subset (c, ligatureArray, this,
+ hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
+
+ return_trace (true);
+ }
+
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
new file mode 100644
index 0000000000..c0eee6d54c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -0,0 +1,36 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOS_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkMarkPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkMarkPosFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
new file mode 100644
index 0000000000..c48a74f773
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
@@ -0,0 +1,227 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix Mark2Array; /* mark2-major--
+ * in order of Mark2Coverage Index--,
+ * mark1-minor--
+ * ordered by class--zero-based. */
+
+struct MarkMarkPosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ mark1Coverage; /* Offset to Combining Mark1 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ Offset16To<Coverage>
+ mark2Coverage; /* Offset to Combining Mark2 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ Offset16To<MarkArray>
+ mark1Array; /* Offset to Mark1Array table--from
+ * beginning of MarkMarkPos subtable */
+ Offset16To<Mark2Array>
+ mark2Array; /* Offset to Mark2Array table--from
+ * beginning of MarkMarkPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (12);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ mark1Coverage.sanitize (c, this) &&
+ mark2Coverage.sanitize (c, this) &&
+ mark1Array.sanitize (c, this) &&
+ mark2Array.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+mark1Coverage).intersects (glyphs) &&
+ (this+mark2Coverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
+
+ unsigned mark2_count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2_count))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : mark2_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+ (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+mark1Coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark1_index == NOT_COVERED)) return_trace (false);
+
+ /* now we search backwards for a suitable mark glyph until a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int j = skippy_iter.idx;
+
+ unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
+
+ if (likely (id1 == id2))
+ {
+ if (id1 == 0) /* Marks belonging to the same base. */
+ goto good;
+ else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
+ goto good;
+ }
+ else
+ {
+ /* If ligature ids don't match, it may be the case that one of the marks
+ * itself is a ligature. In which case match. */
+ if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
+ goto good;
+ }
+
+ /* Didn't match. */
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+
+ good:
+ unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
+ if (mark2_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark1_iter =
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark1_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->mark1Array.serialize_subset (c, mark1Array, this,
+ (this+mark1Coverage).iter (),
+ &klass_mapping);
+
+ unsigned mark2count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2count))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + mark2_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : + mark2_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+
+ out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh
new file mode 100644
index 0000000000..7a514453ae
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh
@@ -0,0 +1,52 @@
+#ifndef OT_LAYOUT_GPOS_MARKRECORD_HH
+#define OT_LAYOUT_GPOS_MARKRECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkRecord
+{
+ friend struct MarkArray;
+
+ protected:
+ HBUINT16 klass; /* Class defined for this mark */
+ Offset16To<Anchor>
+ markAnchor; /* Offset to Anchor table--from
+ * beginning of MarkArray table */
+ public:
+ DEFINE_SIZE_STATIC (4);
+
+ unsigned get_class () const { return (unsigned) klass; }
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
+ }
+
+ MarkRecord *subset (hb_subset_context_t *c,
+ const void *src_base,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->klass = klass_mapping->get (klass);
+ out->markAnchor.serialize_subset (c, markAnchor, src_base);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+markAnchor).collect_variation_indices (c);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKRECORD_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
new file mode 100644
index 0000000000..8479178d38
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
@@ -0,0 +1,38 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOS_HH
+#define OT_LAYOUT_GPOS_PAIRPOS_HH
+
+#include "PairPosFormat1.hh"
+#include "PairPosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PairPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ PairPosFormat1 format1;
+ PairPosFormat2 format2;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOS_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
new file mode 100644
index 0000000000..35a2db2d45
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -0,0 +1,420 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PairValueRecord
+{
+ friend struct PairSet;
+
+ int cmp (hb_codepoint_t k) const
+ { return secondGlyph.cmp (k); }
+
+ struct context_t
+ {
+ const void *base;
+ const ValueFormat *valueFormats;
+ const ValueFormat *newFormats;
+ unsigned len1; /* valueFormats[0].get_len() */
+ const hb_map_t *glyph_map;
+ const hb_map_t *layout_variation_idx_map;
+ };
+
+ bool subset (hb_subset_context_t *c,
+ context_t *closure) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *s = c->serializer;
+ auto *out = s->start_embed (*this);
+ if (unlikely (!s->extend_min (out))) return_trace (false);
+
+ out->secondGlyph = (*closure->glyph_map)[secondGlyph];
+
+ closure->valueFormats[0].copy_values (s,
+ closure->newFormats[0],
+ closure->base, &values[0],
+ closure->layout_variation_idx_map);
+ closure->valueFormats[1].copy_values (s,
+ closure->newFormats[1],
+ closure->base,
+ &values[closure->len1],
+ closure->layout_variation_idx_map);
+
+ return_trace (true);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats,
+ const void *base) const
+ {
+ unsigned record1_len = valueFormats[0].get_len ();
+ unsigned record2_len = valueFormats[1].get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
+
+ if (valueFormats[0].has_device ())
+ valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
+
+ if (valueFormats[1].has_device ())
+ valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
+ }
+
+ bool intersects (const hb_set_t& glyphset) const
+ {
+ return glyphset.has(secondGlyph);
+ }
+
+ const Value* get_values_1 () const
+ {
+ return &values[0];
+ }
+
+ const Value* get_values_2 (ValueFormat format1) const
+ {
+ return &values[format1.get_len ()];
+ }
+
+ protected:
+ HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
+ * pair--first glyph is listed in the
+ * Coverage table */
+ ValueRecord values; /* Positioning data for the first glyph
+ * followed by for second glyph */
+ public:
+ DEFINE_SIZE_ARRAY (2, values);
+};
+
+struct PairSet
+{
+ friend struct PairPosFormat1;
+
+ bool intersects (const hb_set_t *glyphs,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs->has (record->secondGlyph))
+ return true;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ return false;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ c->input->add_array (&record->secondGlyph, len, record_size);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (c->glyph_set->has (record->secondGlyph))
+ { record->collect_variation_indices (c, valueFormats, this); }
+
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ const ValueFormat *valueFormats,
+ unsigned int pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
+ &firstPairValueRecord,
+ len,
+ record_size);
+ if (record)
+ {
+ bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+ bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+ if (len2)
+ pos++;
+ buffer->idx = pos;
+ return_trace (true);
+ }
+ buffer->unsafe_to_concat (buffer->idx, pos + 1);
+ return_trace (false);
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const ValueFormat valueFormats[2],
+ const ValueFormat newFormats[2]) const
+ {
+ TRACE_SUBSET (this);
+ auto snap = c->serializer->snapshot ();
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->len = 0;
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ PairValueRecord::context_t context =
+ {
+ this,
+ valueFormats,
+ newFormats,
+ len1,
+ &glyph_map,
+ c->plan->layout_variation_idx_map
+ };
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len, num = 0;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (glyphset.has (record->secondGlyph)
+ && record->subset (c, &context)) num++;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+
+ out->len = num;
+ if (!num) c->serializer->revert (snap);
+ return_trace (num);
+ }
+
+ struct sanitize_closure_t
+ {
+ const ValueFormat *valueFormats;
+ unsigned int len1; /* valueFormats[0].get_len() */
+ unsigned int stride; /* 1 + len1 + len2 */
+ };
+
+ bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && c->check_range (&firstPairValueRecord,
+ len,
+ HBUINT16::static_size,
+ closure->stride))) return_trace (false);
+
+ unsigned int count = len;
+ const PairValueRecord *record = &firstPairValueRecord;
+ return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+ closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
+ }
+
+ protected:
+ HBUINT16 len; /* Number of PairValueRecords */
+ PairValueRecord firstPairValueRecord;
+ /* Array of PairValueRecords--ordered
+ * by GlyphID of the second glyph */
+ public:
+ DEFINE_SIZE_MIN (2);
+};
+
+struct PairPosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat[2]; /* [0] Defines the types of data in
+ * ValueRecord1--for the first glyph
+ * in the pair--may be zero (0) */
+ /* [1] Defines the types of data in
+ * ValueRecord2--for the second glyph
+ * in the pair--may be zero (0) */
+ Array16OfOffset16To<PairSet>
+ pairSet; /* Array of PairSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (10, pairSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!c->check_struct (this)) return_trace (false);
+
+ unsigned int len1 = valueFormat[0].get_len ();
+ unsigned int len2 = valueFormat[1].get_len ();
+ PairSet::sanitize_closure_t closure =
+ {
+ valueFormat,
+ len1,
+ 1 + len1 + len2
+ };
+
+ return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
+ }
+
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
+ { return (this+_).intersects (glyphs, valueFormat); })
+ | hb_any
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
+
+ auto it =
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ if (!it) return;
+ + it
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ unsigned int count = pairSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ (this+pairSet[i]).collect_glyphs (c, valueFormat);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+ out->valueFormat[0] = valueFormat[0];
+ out->valueFormat[1] = valueFormat[1];
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
+ out->valueFormat[0] = newFormats.first;
+ out->valueFormat[1] = newFormats.second;
+ }
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
+ {
+ auto snap = c->serializer->snapshot ();
+ auto *o = out->pairSet.serialize_append (c->serializer);
+ if (unlikely (!o)) return false;
+ bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
+ if (!ret)
+ {
+ out->pairSet.pop ();
+ c->serializer->revert (snap);
+ }
+ return ret;
+ },
+ hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+
+ return_trace (bool (new_coverage));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+ {
+ unsigned len1 = valueFormat[0].get_len ();
+ unsigned len2 = valueFormat[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+ for (const Offset16To<PairSet>& _ :
+ + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+ {
+ const PairSet& set = (this + _);
+ const PairValueRecord *record = &set.firstPairValueRecord;
+
+ for (unsigned i = 0; i < set.len; i++)
+ {
+ if (record->intersects (glyphset))
+ {
+ format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+ format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+ }
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
new file mode 100644
index 0000000000..3f5f9959c4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -0,0 +1,314 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PairPosFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat1; /* ValueRecord definition--for the
+ * first glyph of the pair--may be zero
+ * (0) */
+ ValueFormat valueFormat2; /* ValueRecord definition--for the
+ * second glyph of the pair--may be
+ * zero (0) */
+ Offset16To<ClassDef>
+ classDef1; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the first glyph of the pair */
+ Offset16To<ClassDef>
+ classDef2; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the second glyph of the pair */
+ HBUINT16 class1Count; /* Number of classes in ClassDef1
+ * table--includes Class0 */
+ HBUINT16 class2Count; /* Number of classes in ClassDef2
+ * table--includes Class0 */
+ ValueRecord values; /* Matrix of value pairs:
+ * class1-major, class2-minor,
+ * Each entry has value1 and value2 */
+ public:
+ DEFINE_SIZE_ARRAY (16, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && coverage.sanitize (c, this)
+ && classDef1.sanitize (c, this)
+ && classDef2.sanitize (c, this))) return_trace (false);
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ unsigned int stride = len1 + len2;
+ unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
+ unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
+ return_trace (c->check_range ((const void *) values,
+ count,
+ record_size) &&
+ valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+coverage).intersects (glyphs) &&
+ (this+classDef2).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!intersects (c->glyph_set)) return;
+ if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
+
+ hb_set_t klass1_glyphs, klass2_glyphs;
+ if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
+ if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
+
+ hb_set_t class1_set, class2_set;
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
+ {
+ if (!klass1_glyphs.has (cp)) class1_set.add (0);
+ else
+ {
+ unsigned klass1 = (this+classDef1).get (cp);
+ class1_set.add (klass1);
+ }
+ }
+
+ class2_set.add (0);
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
+ {
+ unsigned klass2 = (this+classDef2).get (cp);
+ class2_set.add (klass2);
+ }
+
+ if (class1_set.is_empty ()
+ || class2_set.is_empty ()
+ || (class2_set.get_population() == 1 && class2_set.has(0)))
+ return;
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
+ for (const unsigned class1_idx : class1_set.iter ())
+ {
+ for (const unsigned class2_idx : class2_set.iter ())
+ {
+ unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ if (valueFormat1.has_device ())
+ valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
+
+ if (valueFormat2.has_device ())
+ valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
+ }
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ unsigned int record_len = len1 + len2;
+
+ unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
+ unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+ if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
+ {
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+ return_trace (false);
+ }
+
+ const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
+
+ bool applied_first = false, applied_second = false;
+
+
+ /* Isolate simple kerning and apply it half to each side.
+ * Results in better cursor positinoing / underline drawing.
+ *
+ * Disabled, because causes issues... :-(
+ * https://github.com/harfbuzz/harfbuzz/issues/3408
+ * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
+ */
+#ifndef HB_SPLIT_KERN
+ if (0)
+#endif
+ {
+ if (!len2)
+ {
+ const hb_direction_t dir = buffer->props.direction;
+ const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
+ const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
+ unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
+ if (backward)
+ mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
+ /* Add Devices. */
+ mask |= mask << 4;
+
+ if (valueFormat1 & ~mask)
+ goto bail;
+
+ /* Is simple kern. Apply value on an empty position slot,
+ * then split it between sides. */
+
+ hb_glyph_position_t pos{};
+ if (valueFormat1.apply_value (c, this, v, pos))
+ {
+ hb_position_t *src = &pos.x_advance;
+ hb_position_t *dst1 = &buffer->cur_pos().x_advance;
+ hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
+ unsigned i = horizontal ? 0 : 1;
+
+ hb_position_t kern = src[i];
+ hb_position_t kern1 = kern >> 1;
+ hb_position_t kern2 = kern - kern1;
+
+ if (!backward)
+ {
+ dst1[i] += kern1;
+ dst2[i] += kern2;
+ dst2[i + 2] += kern2;
+ }
+ else
+ {
+ dst1[i] += kern1;
+ dst1[i + 2] += src[i + 2] - kern2;
+ dst2[i] += kern2;
+ }
+
+ applied_first = applied_second = kern != 0;
+ goto success;
+ }
+ goto boring;
+ }
+ }
+ bail:
+
+
+ applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+ applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+
+ success:
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ else
+ boring:
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+
+
+ buffer->idx = skippy_iter.idx;
+ if (len2)
+ buffer->idx++;
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass1_map;
+ out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
+ out->class1Count = klass1_map.get_population ();
+
+ hb_map_t klass2_map;
+ out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
+ out->class2Count = klass2_map.get_population ();
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ newFormats = compute_effective_value_formats (klass1_map, klass2_map);
+
+ out->valueFormat1 = newFormats.first;
+ out->valueFormat2 = newFormats.second;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
+ valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
+ }
+ }
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ out->coverage.serialize_serialize (c->serializer, it);
+ return_trace (out->class1Count && out->class2Count && bool (it));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
+ const hb_map_t& klass2_map) const
+ {
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+ format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh
new file mode 100644
index 0000000000..c4e57bb543
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUP_HH
+#define OT_LAYOUT_GPOS_POSLOOKUP_HH
+
+#include "PosLookupSubTable.hh"
+#include "../../../hb-ot-layout-common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookup : Lookup
+{
+ using SubTable = PosLookupSubTable;
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ bool is_reverse () const
+ {
+ return false;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { return dispatch (c); }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ template <typename context_t>
+ static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_POSLOOKUP_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh
new file mode 100644
index 0000000000..c19fbc323f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+
+#include "SinglePos.hh"
+#include "PairPos.hh"
+#include "CursivePos.hh"
+#include "MarkBasePos.hh"
+#include "MarkLigPos.hh"
+#include "MarkMarkPos.hh"
+#include "ContextPos.hh"
+#include "ChainContextPos.hh"
+#include "ExtensionPos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct PosLookup;
+
+ enum Type {
+ Single = 1,
+ Pair = 2,
+ Cursive = 3,
+ MarkBase = 4,
+ MarkLig = 5,
+ MarkMark = 6,
+ Context = 7,
+ ChainContext = 8,
+ Extension = 9
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
+ case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+
+ protected:
+ union {
+ SinglePos single;
+ PairPos pair;
+ CursivePos cursive;
+ MarkBasePos markBase;
+ MarkLigPos markLig;
+ MarkMarkPos markMark;
+ ContextPos context;
+ ChainContextPos chainContext;
+ ExtensionPos extension;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh
new file mode 100644
index 0000000000..57e146befd
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh
@@ -0,0 +1,98 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOS_HH
+#define OT_LAYOUT_GPOS_SINGLEPOS_HH
+
+#include "SinglePosFormat1.hh"
+#include "SinglePosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SinglePosFormat1 format1;
+ SinglePosFormat2 format2;
+ } u;
+
+ public:
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned get_format (Iterator glyph_val_iter_pairs)
+ {
+ hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+
+ for (const auto iter : glyph_val_iter_pairs)
+ for (const auto _ : hb_zip (iter.second, first_val_iter))
+ if (_.first != _.second)
+ return 2;
+
+ return 1;
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup* src,
+ Iterator glyph_val_iter_pairs,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ if (unlikely (!c->extend_min (u.format))) return;
+ unsigned format = 2;
+ ValueFormat new_format = src->get_value_format ();
+
+ if (glyph_val_iter_pairs)
+ {
+ format = get_format (glyph_val_iter_pairs);
+ new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
+ }
+
+ u.format = format;
+ switch (u.format) {
+ case 1: u.format1.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
+ case 2: u.format2.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
+ default:return;
+ }
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+template<typename Iterator, typename SrcLookup>
+static void
+SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_map_t *layout_variation_idx_map)
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh
new file mode 100644
index 0000000000..8b7840ed0e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -0,0 +1,124 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+
+#include "Common.hh"
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ ValueRecord values; /* Defines positioning
+ * value(s)--applied to all glyphs in
+ * the Coverage table */
+ public:
+ DEFINE_SIZE_ARRAY (6, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_value (c, this, values));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (c->glyph_set)
+ ;
+
+ if (!it) return;
+ valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ valueFormat.apply_value (c, this, values, buffer->cur_pos());
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ if (unlikely (!c->extend_min (this))) return;
+ if (unlikely (!c->check_assign (valueFormat,
+ newFormat,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+
+ for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
+ {
+ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
+ // Only serialize the first entry in the iterator, the rest are assumed to
+ // be the same.
+ break;
+ }
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh
new file mode 100644
index 0000000000..0d038b4422
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -0,0 +1,140 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ HBUINT16 valueCount; /* Number of ValueRecords */
+ ValueRecord values; /* Array of ValueRecords--positioning
+ * values applied to glyphs */
+ public:
+ DEFINE_SIZE_ARRAY (8, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_values (c, this, values, valueCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (c->glyph_set, hb_first)
+ ;
+
+ if (!it) return;
+
+ unsigned sub_length = valueFormat.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
+
+ for (unsigned i : + it
+ | hb_map (hb_second))
+ valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
+
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (likely (index >= valueCount)) return_trace (false);
+
+ valueFormat.apply_value (c, this,
+ &values[index * valueFormat.get_len ()],
+ buffer->cur_pos());
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ auto out = c->extend_min (this);
+ if (unlikely (!out)) return;
+ if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+ if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
+
+ + it
+ | hb_map (hb_second)
+ | hb_apply ([&] (hb_array_t<const Value> _)
+ { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
+ ;
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned sub_length = valueFormat.get_len ();
+ auto values_array = values.as_array (valueCount * sub_length);
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
+ {
+ return hb_pair (glyph_map[_.first],
+ values_array.sub_array (_.second * sub_length,
+ sub_length));
+ })
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh
new file mode 100644
index 0000000000..b29f287bce
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh
@@ -0,0 +1,329 @@
+#ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
+#define OT_LAYOUT_GPOS_VALUEFORMAT_HH
+
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef HBUINT16 Value;
+
+typedef UnsizedArrayOf<Value> ValueRecord;
+
+struct ValueFormat : HBUINT16
+{
+ enum Flags {
+ xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
+ yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
+ xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
+ yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
+ xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
+ yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
+ xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
+ yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
+ ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
+ reserved = 0xF000u, /* For future use */
+
+ devices = 0x00F0u /* Mask for having any Device table */
+ };
+
+/* All fields are options. Only those available advance the value pointer. */
+#if 0
+ HBINT16 xPlacement; /* Horizontal adjustment for
+ * placement--in design units */
+ HBINT16 yPlacement; /* Vertical adjustment for
+ * placement--in design units */
+ HBINT16 xAdvance; /* Horizontal adjustment for
+ * advance--in design units (only used
+ * for horizontal writing) */
+ HBINT16 yAdvance; /* Vertical adjustment for advance--in
+ * design units (only used for vertical
+ * writing) */
+ Offset16To<Device> xPlaDevice; /* Offset to Device table for
+ * horizontal placement--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
+ * placement--measured from beginning
+ * of PosTable (may be NULL) */
+ Offset16To<Device> xAdvDevice; /* Offset to Device table for
+ * horizontal advance--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
+ * advance--measured from beginning of
+ * PosTable (may be NULL) */
+#endif
+
+ IntType& operator = (uint16_t i) { v = i; return *this; }
+
+ unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
+ unsigned int get_size () const { return get_len () * Value::static_size; }
+
+ bool apply_value (hb_ot_apply_context_t *c,
+ const void *base,
+ const Value *values,
+ hb_glyph_position_t &glyph_pos) const
+ {
+ bool ret = false;
+ unsigned int format = *this;
+ if (!format) return ret;
+
+ hb_font_t *font = c->font;
+ bool horizontal =
+#ifndef HB_NO_VERTICAL
+ HB_DIRECTION_IS_HORIZONTAL (c->direction)
+#else
+ true
+#endif
+ ;
+
+ if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
+ if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
+ if (format & xAdvance) {
+ if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
+ values++;
+ }
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (format & yAdvance) {
+ if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
+ values++;
+ }
+
+ if (!has_device ()) return ret;
+
+ bool use_x_device = font->x_ppem || font->num_coords;
+ bool use_y_device = font->y_ppem || font->num_coords;
+
+ if (!use_x_device && !use_y_device) return ret;
+
+ const VariationStore &store = c->var_store;
+ auto *cache = c->var_store_cache;
+
+ /* pixel -> fractional pixel */
+ if (format & xPlaDevice) {
+ if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yPlaDevice) {
+ if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ if (format & xAdvDevice) {
+ if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yAdvDevice) {
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ return ret;
+ }
+
+ unsigned int get_effective_format (const Value *values) const
+ {
+ unsigned int format = *this;
+ for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+ if (format & flag) should_drop (*values++, (Flags) flag, &format);
+ }
+
+ return format;
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned int get_effective_format (Iterator it) const {
+ unsigned int new_format = 0;
+
+ for (const hb_array_t<const Value>& values : it)
+ new_format = new_format | get_effective_format (&values);
+
+ return new_format;
+ }
+
+ void copy_values (hb_serialize_context_t *c,
+ unsigned int new_format,
+ const void *base,
+ const Value *values,
+ const hb_map_t *layout_variation_idx_map) const
+ {
+ unsigned int format = *this;
+ if (!format) return;
+
+ if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
+ if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
+ if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
+ if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
+
+ if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ }
+
+ void copy_value (hb_serialize_context_t *c,
+ unsigned int new_format,
+ Flags flag,
+ Value value) const
+ {
+ // Filter by new format.
+ if (!(new_format & flag)) return;
+ c->copy (value);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *base,
+ const hb_array_t<const Value>& values) const
+ {
+ unsigned format = *this;
+ unsigned i = 0;
+ if (format & xPlacement) i++;
+ if (format & yPlacement) i++;
+ if (format & xAdvance) i++;
+ if (format & yAdvance) i++;
+ if (format & xPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::yPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::xAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::yAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+ }
+
+ private:
+ bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ unsigned int format = *this;
+
+ if (format & xPlacement) values++;
+ if (format & yPlacement) values++;
+ if (format & xAdvance) values++;
+ if (format & yAdvance) values++;
+
+ if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+
+ return true;
+ }
+
+ static inline Offset16To<Device>& get_device (Value* value)
+ {
+ return *static_cast<Offset16To<Device> *> (value);
+ }
+ static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *static_cast<const Offset16To<Device> *> (value);
+ }
+
+ bool copy_device (hb_serialize_context_t *c, const void *base,
+ const Value *src_value, const hb_map_t *layout_variation_idx_map) const
+ {
+ Value *dst_value = c->copy (*src_value);
+
+ if (!dst_value) return false;
+ if (*dst_value == 0) return true;
+
+ *dst_value = 0;
+ c->push ();
+ if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
+ {
+ c->add_link (*dst_value, c->pop_pack ());
+ return true;
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+
+ static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *reinterpret_cast<const HBINT16 *> (value);
+ }
+
+ public:
+
+ bool has_device () const
+ {
+ unsigned int format = *this;
+ return (format & devices) != 0;
+ }
+
+ bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+ }
+
+ bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+ {
+ TRACE_SANITIZE (this);
+ unsigned int len = get_len ();
+
+ if (!c->check_range (values, count, get_size ())) return_trace (false);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values += len;
+ }
+
+ return_trace (true);
+ }
+
+ /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
+ bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values += stride;
+ }
+
+ return_trace (true);
+ }
+
+ private:
+
+ void should_drop (Value value, Flags flag, unsigned int* format) const
+ {
+ if (value) return;
+ *format = *format & ~flag;
+ }
+
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
index ad153ce8d7..3f0c4b2ad9 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
@@ -19,6 +19,8 @@ namespace GSUB {
struct GSUB : GSUBGPOS
{
+ using Lookup = SubstLookup;
+
static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
const SubstLookup& get_lookup (unsigned int i) const
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
index 3419b5a734..8fb3b55097 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
@@ -10,7 +10,7 @@ namespace GSUB {
struct SubstLookup : Lookup
{
- typedef SubstLookupSubTable SubTable;
+ using SubTable = SubstLookupSubTable;
bool sanitize (hb_sanitize_context_t *c) const
{ return Lookup::sanitize<SubTable> (c); }
@@ -73,8 +73,6 @@ struct SubstLookup : Lookup
return hb_closure_lookups_context_t::default_return_value ();
}
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
hb_closure_lookups_context_t::return_t ret = dispatch (c);
return ret;
}
@@ -100,8 +98,6 @@ struct SubstLookup : Lookup
return dispatch (c);
}
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
bool serialize_single (hb_serialize_context_t *c,
uint32_t lookup_props,
hb_sorted_array_t<const HBGlyphID16> glyphs,
@@ -206,8 +202,6 @@ struct SubstLookup : Lookup
return ret;
}
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
-
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
new file mode 100644
index 0000000000..c145beaa49
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
@@ -0,0 +1,258 @@
+#ifndef OT_GLYF_COMPOSITEGLYPH_HH
+#define OT_GLYF_COMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct CompositeGlyphRecord
+{
+ protected:
+ enum composite_glyph_flag_t
+ {
+ ARG_1_AND_2_ARE_WORDS = 0x0001,
+ ARGS_ARE_XY_VALUES = 0x0002,
+ ROUND_XY_TO_GRID = 0x0004,
+ WE_HAVE_A_SCALE = 0x0008,
+ MORE_COMPONENTS = 0x0020,
+ WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
+ WE_HAVE_A_TWO_BY_TWO = 0x0080,
+ WE_HAVE_INSTRUCTIONS = 0x0100,
+ USE_MY_METRICS = 0x0200,
+ OVERLAP_COMPOUND = 0x0400,
+ SCALED_COMPONENT_OFFSET = 0x0800,
+ UNSCALED_COMPONENT_OFFSET = 0x1000
+ };
+
+ public:
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+ /* arg1 and 2 are int16 */
+ if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+ /* arg1 and 2 are int8 */
+ else size += 2;
+
+ /* One x 16 bit (scale) */
+ if (flags & WE_HAVE_A_SCALE) size += 2;
+ /* Two x 16 bit (xscale, yscale) */
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+ /* Four x 16 bit (xscale, scale01, scale10, yscale) */
+ else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
+ return size;
+ }
+
+ void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
+ void set_overlaps_flag ()
+ {
+ flags = (uint16_t) flags | OVERLAP_COMPOUND;
+ }
+
+ bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
+
+ bool has_more () const { return flags & MORE_COMPONENTS; }
+ bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+ bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
+ void get_anchor_points (unsigned int &point1, unsigned int &point2) const
+ {
+ const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ point1 = ((const HBUINT16 *) p)[0];
+ point2 = ((const HBUINT16 *) p)[1];
+ }
+ else
+ {
+ point1 = p[0];
+ point2 = p[1];
+ }
+ }
+
+ void transform_points (contour_point_vector_t &points) const
+ {
+ float matrix[4];
+ contour_point_t trans;
+ if (get_transformation (matrix, trans))
+ {
+ if (scaled_offsets ())
+ {
+ points.translate (trans);
+ points.transform (matrix);
+ }
+ else
+ {
+ points.transform (matrix);
+ points.translate (trans);
+ }
+ }
+ }
+
+ protected:
+ bool scaled_offsets () const
+ { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
+
+ bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
+ {
+ matrix[0] = matrix[3] = 1.f;
+ matrix[1] = matrix[2] = 0.f;
+
+ int tx, ty;
+ const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ tx = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ ty = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ else
+ {
+ tx = *p++;
+ ty = *p++;
+ }
+ if (is_anchored ()) tx = ty = 0;
+
+ trans.init ((float) tx, (float) ty);
+
+ {
+ const F2DOT14 *points = (const F2DOT14 *) p;
+ if (flags & WE_HAVE_A_SCALE)
+ {
+ matrix[0] = matrix[3] = points[0].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[3] = points[1].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[1] = points[1].to_float ();
+ matrix[2] = points[2].to_float ();
+ matrix[3] = points[3].to_float ();
+ return true;
+ }
+ }
+ return tx || ty;
+ }
+
+ public:
+ HBUINT16 flags;
+ HBGlyphID16 glyphIndex;
+ public:
+ DEFINE_SIZE_MIN (4);
+};
+
+struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &>
+{
+ typedef const CompositeGlyphRecord *__item_t__;
+ composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
+ glyph (glyph_), current (nullptr), current_size (0)
+ {
+ set_current (current_);
+ }
+
+ composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
+
+ item_t __item__ () const { return *current; }
+ bool __more__ () const { return current; }
+ void __next__ ()
+ {
+ if (!current->has_more ()) { current = nullptr; return; }
+
+ set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
+ }
+ composite_iter_t __end__ () const { return composite_iter_t (); }
+ bool operator != (const composite_iter_t& o) const
+ { return current != o.current; }
+
+
+ void set_current (__item_t__ current_)
+ {
+ if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+ unsigned size = current_->get_size ();
+ if (!glyph.check_range (current_, size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+
+ current = current_;
+ current_size = size;
+ }
+
+ private:
+ hb_bytes_t glyph;
+ __item_t__ current;
+ unsigned current_size;
+};
+
+struct CompositeGlyph
+{
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ composite_iter_t iter () const
+ { return composite_iter_t (bytes, &StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); }
+
+ unsigned int instructions_length (hb_bytes_t bytes) const
+ {
+ unsigned int start = bytes.length;
+ unsigned int end = bytes.length;
+ const CompositeGlyphRecord *last = nullptr;
+ for (auto &item : iter ())
+ last = &item;
+ if (unlikely (!last)) return 0;
+
+ if (last->has_instructions ())
+ start = (char *) last - &bytes + last->get_size ();
+ if (unlikely (start > end)) return 0;
+ return end - start;
+ }
+
+ /* Trimming for composites not implemented.
+ * If removing hints it falls out of that. */
+ const hb_bytes_t trim_padding () const { return bytes; }
+
+ void drop_hints ()
+ {
+ for (const auto &_ : iter ())
+ const_cast<CompositeGlyphRecord &> (_).drop_instructions_flag ();
+ }
+
+ /* Chop instructions off the end */
+ void drop_hints_bytes (hb_bytes_t &dest_start) const
+ { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+ void set_overlaps_flag ()
+ {
+ CompositeGlyphRecord& glyph_chain = const_cast<CompositeGlyphRecord &> (
+ StructAfter<CompositeGlyphRecord, GlyphHeader> (header));
+ if (!bytes.check_range(&glyph_chain, CompositeGlyphRecord::min_size))
+ return;
+ glyph_chain.set_overlaps_flag ();
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_COMPOSITEGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
new file mode 100644
index 0000000000..2199d2c48b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
@@ -0,0 +1,233 @@
+#ifndef OT_GLYF_GLYPH_HH
+#define OT_GLYF_GLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+#include "GlyphHeader.hh"
+#include "SimpleGlyph.hh"
+#include "CompositeGlyph.hh"
+
+
+namespace OT {
+
+struct glyf_accelerator_t;
+
+namespace glyf_impl {
+
+
+enum phantom_point_index_t
+{
+ PHANTOM_LEFT = 0,
+ PHANTOM_RIGHT = 1,
+ PHANTOM_TOP = 2,
+ PHANTOM_BOTTOM = 3,
+ PHANTOM_COUNT = 4
+};
+
+struct Glyph
+{
+ enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
+
+ public:
+ composite_iter_t get_composite_iterator () const
+ {
+ if (type != COMPOSITE) return composite_iter_t ();
+ return CompositeGlyph (*header, bytes).iter ();
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ switch (type) {
+ case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
+ case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
+ default: return bytes;
+ }
+ }
+
+ void drop_hints ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
+ default: return;
+ }
+ }
+
+ void set_overlaps_flag ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+ default: return;
+ }
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
+ default: return;
+ }
+ }
+
+ /* Note: Recursively calls itself.
+ * all_points includes phantom points
+ */
+ template <typename accelerator_t>
+ bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
+ contour_point_vector_t &all_points /* OUT */,
+ bool phantom_only = false,
+ unsigned int depth = 0) const
+ {
+ if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+ contour_point_vector_t stack_points;
+ bool inplace = type == SIMPLE && all_points.length == 0;
+ /* Load into all_points if it's empty, as an optimization. */
+ contour_point_vector_t &points = inplace ? all_points : stack_points;
+
+ switch (type) {
+ case COMPOSITE:
+ {
+ /* pseudo component points for each component in composite glyph */
+ unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
+ if (unlikely (!points.resize (num_points))) return false;
+ break;
+ }
+ case SIMPLE:
+ if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+ return false;
+ break;
+ }
+
+ /* Init phantom points */
+ if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
+ hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+ {
+ int h_delta = (int) header->xMin -
+ glyf_accelerator.hmtx->get_side_bearing (gid);
+ int v_orig = (int) header->yMax +
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_side_bearing (gid)
+#else
+ 0
+#endif
+ ;
+ unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
+ unsigned v_adv =
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_advance (gid)
+#else
+ - font->face->get_upem ()
+#endif
+ ;
+ phantoms[PHANTOM_LEFT].x = h_delta;
+ phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
+ phantoms[PHANTOM_TOP].y = v_orig;
+ phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
+ }
+
+#ifndef HB_NO_VAR
+ glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
+#endif
+
+ switch (type) {
+ case SIMPLE:
+ if (!inplace)
+ all_points.extend (points.as_array ());
+ break;
+ case COMPOSITE:
+ {
+ contour_point_vector_t comp_points;
+ unsigned int comp_index = 0;
+ for (auto &item : get_composite_iterator ())
+ {
+ comp_points.reset ();
+ if (unlikely (!glyf_accelerator.glyph_for_gid (item.glyphIndex)
+ .get_points (font, glyf_accelerator, comp_points,
+ phantom_only, depth + 1)))
+ return false;
+
+ /* Copy phantom points from component if USE_MY_METRICS flag set */
+ if (item.is_use_my_metrics ())
+ for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+ phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+ /* Apply component transformation & translation */
+ item.transform_points (comp_points);
+
+ /* Apply translation from gvar */
+ comp_points.translate (points[comp_index]);
+
+ if (item.is_anchored ())
+ {
+ unsigned int p1, p2;
+ item.get_anchor_points (p1, p2);
+ if (likely (p1 < all_points.length && p2 < comp_points.length))
+ {
+ contour_point_t delta;
+ delta.init (all_points[p1].x - comp_points[p2].x,
+ all_points[p1].y - comp_points[p2].y);
+
+ comp_points.translate (delta);
+ }
+ }
+
+ all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+ comp_index++;
+ }
+
+ all_points.extend (phantoms);
+ } break;
+ default:
+ all_points.extend (phantoms);
+ }
+
+ if (depth == 0) /* Apply at top level */
+ {
+ /* Undocumented rasterizer behavior:
+ * Shift points horizontally by the updated left side bearing
+ */
+ contour_point_t delta;
+ delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
+ if (delta.x) all_points.translate (delta);
+ }
+
+ return !all_points.in_error ();
+ }
+
+ bool get_extents (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
+ hb_glyph_extents_t *extents) const
+ {
+ if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+ return header->get_extents (font, glyf_accelerator, gid, extents);
+ }
+
+ hb_bytes_t get_bytes () const { return bytes; }
+
+ Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
+ hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
+ header (bytes.as<GlyphHeader> ()),
+ gid (gid_)
+ {
+ int num_contours = header->numberOfContours;
+ if (unlikely (num_contours == 0)) type = EMPTY;
+ else if (num_contours > 0) type = SIMPLE;
+ else type = COMPOSITE; /* negative numbers */
+ }
+
+ protected:
+ hb_bytes_t bytes;
+ const GlyphHeader *header;
+ hb_codepoint_t gid;
+ unsigned type;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh
new file mode 100644
index 0000000000..792bd5478f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh
@@ -0,0 +1,48 @@
+#ifndef OT_GLYF_GLYPHHEADER_HH
+#define OT_GLYF_GLYPHHEADER_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct GlyphHeader
+{
+ bool has_data () const { return numberOfContours; }
+
+ template <typename accelerator_t>
+ bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
+ hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
+ /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
+ extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
+ extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
+ extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
+ extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
+
+ return true;
+ }
+
+ HBINT16 numberOfContours;
+ /* If the number of contours is
+ * greater than or equal to zero,
+ * this is a simple glyph; if negative,
+ * this is a composite glyph. */
+ FWORD xMin; /* Minimum x for coordinate data. */
+ FWORD yMin; /* Minimum y for coordinate data. */
+ FWORD xMax; /* Maximum x for coordinate data. */
+ FWORD yMax; /* Maximum y for coordinate data. */
+ public:
+ DEFINE_SIZE_STATIC (10);
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPHHEADER_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
new file mode 100644
index 0000000000..6df978cf13
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
@@ -0,0 +1,216 @@
+#ifndef OT_GLYF_SIMPLEGLYPH_HH
+#define OT_GLYF_SIMPLEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct SimpleGlyph
+{
+ enum simple_glyph_flag_t
+ {
+ FLAG_ON_CURVE = 0x01,
+ FLAG_X_SHORT = 0x02,
+ FLAG_Y_SHORT = 0x04,
+ FLAG_REPEAT = 0x08,
+ FLAG_X_SAME = 0x10,
+ FLAG_Y_SAME = 0x20,
+ FLAG_OVERLAP_SIMPLE = 0x40,
+ FLAG_RESERVED2 = 0x80
+ };
+
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ unsigned int instruction_len_offset () const
+ { return GlyphHeader::static_size + 2 * header.numberOfContours; }
+
+ unsigned int length (unsigned int instruction_len) const
+ { return instruction_len_offset () + 2 + instruction_len; }
+
+ unsigned int instructions_length () const
+ {
+ unsigned int instruction_length_offset = instruction_len_offset ();
+ if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
+
+ const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
+ /* Out of bounds of the current glyph */
+ if (unlikely (length (instructionLength) > bytes.length)) return 0;
+ return instructionLength;
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ /* based on FontTools _g_l_y_f.py::trim */
+ const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
+ const uint8_t *glyph_end = glyph + bytes.length;
+ /* simple glyph w/contours, possibly trimmable */
+ glyph += instruction_len_offset ();
+
+ if (unlikely (glyph + 2 >= glyph_end)) return hb_bytes_t ();
+ unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+ unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
+
+ glyph += 2 + num_instructions;
+
+ unsigned int coord_bytes = 0;
+ unsigned int coords_with_flags = 0;
+ while (glyph < glyph_end)
+ {
+ uint8_t flag = *glyph;
+ glyph++;
+
+ unsigned int repeat = 1;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (glyph >= glyph_end)) return hb_bytes_t ();
+ repeat = *glyph + 1;
+ glyph++;
+ }
+
+ unsigned int xBytes, yBytes;
+ xBytes = yBytes = 0;
+ if (flag & FLAG_X_SHORT) xBytes = 1;
+ else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
+
+ if (flag & FLAG_Y_SHORT) yBytes = 1;
+ else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
+
+ coord_bytes += (xBytes + yBytes) * repeat;
+ coords_with_flags += repeat;
+ if (coords_with_flags >= num_coordinates) break;
+ }
+
+ if (unlikely (coords_with_flags != num_coordinates)) return hb_bytes_t ();
+ return bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph));
+ }
+
+ /* zero instruction length */
+ void drop_hints ()
+ {
+ GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
+ (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ unsigned int instructions_len = instructions_length ();
+ unsigned int glyph_length = length (instructions_len);
+ dest_start = bytes.sub_array (0, glyph_length - instructions_len);
+ dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
+ }
+
+ void set_overlaps_flag ()
+ {
+ if (unlikely (!header.numberOfContours)) return;
+
+ unsigned flags_offset = length (instructions_length ());
+ if (unlikely (flags_offset + 1 > bytes.length)) return;
+
+ HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
+ first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
+ }
+
+ static bool read_flags (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end)
+ {
+ unsigned count = points_.length;
+ for (unsigned int i = 0; i < count;)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ uint8_t flag = *p++;
+ points_.arrayZ[i++].flag = flag;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ unsigned int repeat_count = *p++;
+ unsigned stop = hb_min (i + repeat_count, count);
+ for (; i < stop;)
+ points_.arrayZ[i++].flag = flag;
+ }
+ }
+ return true;
+ }
+
+ static bool read_points (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end,
+ float contour_point_t::*m,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag)
+ {
+ int v = 0;
+
+ unsigned count = points_.length;
+ for (unsigned i = 0; i < count; i++)
+ {
+ unsigned flag = points_[i].flag;
+ if (flag & short_flag)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ if (flag & same_flag)
+ v += *p++;
+ else
+ v -= *p++;
+ }
+ else
+ {
+ if (!(flag & same_flag))
+ {
+ if (unlikely (p + HBINT16::static_size > end)) return false;
+ v += *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ }
+ points_.arrayZ[i].*m = v;
+ }
+ return true;
+ }
+
+ bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+ bool phantom_only = false) const
+ {
+ const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
+ int num_contours = header.numberOfContours;
+ assert (num_contours);
+ /* One extra item at the end, for the instruction-count below. */
+ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
+ unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
+
+ points_.alloc (num_points + 4); // Allocate for phantom points, to avoid a possible copy
+ if (!points_.resize (num_points)) return false;
+ if (phantom_only) return true;
+
+ for (int i = 0; i < num_contours; i++)
+ points_[endPtsOfContours[i]].is_end_point = true;
+
+ /* Skip instructions */
+ const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
+ endPtsOfContours[num_contours]);
+
+ if (unlikely ((const char *) p < bytes.arrayZ)) return false; /* Unlikely overflow */
+ const HBUINT8 *end = (const HBUINT8 *) (bytes.arrayZ + bytes.length);
+ if (unlikely (p >= end)) return false;
+
+ /* Read x & y coordinates */
+ return read_flags (p, points_, end)
+ && read_points (p, points_, end, &contour_point_t::x,
+ FLAG_X_SHORT, FLAG_X_SAME)
+ && read_points (p, points_, end, &contour_point_t::y,
+ FLAG_Y_SHORT, FLAG_Y_SAME);
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SIMPLEGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
new file mode 100644
index 0000000000..ebe4372047
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
@@ -0,0 +1,72 @@
+#ifndef OT_GLYF_SUBSETGLYPH_HH
+#define OT_GLYF_SUBSETGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct SubsetGlyph
+{
+ hb_codepoint_t new_gid;
+ hb_codepoint_t old_gid;
+ Glyph source_glyph;
+ hb_bytes_t dest_start; /* region of source_glyph to copy first */
+ hb_bytes_t dest_end; /* region of source_glyph to copy second */
+
+ bool serialize (hb_serialize_context_t *c,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan) const
+ {
+ TRACE_SERIALIZE (this);
+
+ hb_bytes_t dest_glyph = dest_start.copy (c);
+ dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
+ unsigned int pad_length = use_short_loca ? padding () : 0;
+ DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
+
+ HBUINT8 pad;
+ pad = 0;
+ while (pad_length > 0)
+ {
+ c->embed (pad);
+ pad_length--;
+ }
+
+ if (unlikely (!dest_glyph.length)) return_trace (true);
+
+ /* update components gids */
+ for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
+ {
+ hb_codepoint_t new_gid;
+ if (plan->new_gid_for_old_gid (_.glyphIndex, &new_gid))
+ const_cast<CompositeGlyphRecord &> (_).glyphIndex = new_gid;
+ }
+
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ Glyph (dest_glyph).drop_hints ();
+
+ if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
+ Glyph (dest_glyph).set_overlaps_flag ();
+
+ return_trace (true);
+ }
+
+ void drop_hints_bytes ()
+ { source_glyph.drop_hints_bytes (dest_start, dest_end); }
+
+ unsigned int length () const { return dest_start.length + dest_end.length; }
+ /* pad to 2 to ensure 2-byte loca will be ok */
+ unsigned int padding () const { return length () % 2; }
+ unsigned int padded_size () const { return length () + padding (); }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SUBSETGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
new file mode 100644
index 0000000000..f51f7a81fc
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
@@ -0,0 +1,90 @@
+#ifndef OT_GLYF_GLYF_HELPERS_HH
+#define OT_GLYF_GLYF_HELPERS_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-subset-plan.hh"
+
+#include "loca.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template<typename IteratorIn, typename IteratorOut,
+ hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
+ hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+static void
+_write_loca (IteratorIn it, bool short_offsets, IteratorOut dest)
+{
+ unsigned right_shift = short_offsets ? 1 : 0;
+ unsigned int offset = 0;
+ dest << 0;
+ + it
+ | hb_map ([=, &offset] (unsigned int padded_size)
+ {
+ offset += padded_size;
+ DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
+ return offset >> right_shift;
+ })
+ | hb_sink (dest)
+ ;
+}
+
+static bool
+_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
+{
+ hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
+ hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
+ hb_blob_destroy (head_blob);
+
+ if (unlikely (!head_prime_blob))
+ return false;
+
+ head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+ head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
+ bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
+
+ hb_blob_destroy (head_prime_blob);
+ return success;
+}
+
+template<typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, unsigned int))>
+static bool
+_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
+{
+ unsigned num_offsets = padded_offsets.len () + 1;
+ unsigned entry_size = use_short_loca ? 2 : 4;
+ char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
+
+ if (unlikely (!loca_prime_data)) return false;
+
+ DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
+ entry_size, num_offsets, entry_size * num_offsets);
+
+ if (use_short_loca)
+ _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
+ else
+ _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
+
+ hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
+ entry_size * num_offsets,
+ HB_MEMORY_MODE_WRITABLE,
+ loca_prime_data,
+ hb_free);
+
+ bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
+ && _add_head_and_set_loca_version (plan, use_short_loca);
+
+ hb_blob_destroy (loca_blob);
+ return result;
+}
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HELPERS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
new file mode 100644
index 0000000000..f74513cb96
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
@@ -0,0 +1,388 @@
+#ifndef OT_GLYF_GLYF_HH
+#define OT_GLYF_GLYF_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-ot-head-table.hh"
+#include "../../hb-ot-hmtx-table.hh"
+#include "../../hb-ot-var-gvar-table.hh"
+#include "../../hb-draw.hh"
+
+#include "glyf-helpers.hh"
+#include "Glyph.hh"
+#include "SubsetGlyph.hh"
+#include "loca.hh"
+#include "path-builder.hh"
+
+
+namespace OT {
+
+
+/*
+ * glyf -- TrueType Glyph Data
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
+ */
+#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
+
+
+struct glyf
+{
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ /* Runtime checks as eager sanitizing each glyph is costy */
+ return_trace (true);
+ }
+
+ /* requires source of SubsetGlyph complains the identifier isn't declared */
+ template <typename Iterator>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan)
+ {
+ TRACE_SERIALIZE (this);
+ unsigned init_len = c->length ();
+ for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
+
+ /* As a special case when all glyph in the font are empty, add a zero byte
+ * to the table, so that OTS doesn’t reject it, and to make the table work
+ * on Windows as well.
+ * See https://github.com/khaledhosny/ots/issues/52 */
+ if (init_len == c->length ())
+ {
+ HBUINT8 empty_byte;
+ empty_byte = 0;
+ c->copy (empty_byte);
+ }
+ return_trace (true);
+ }
+
+ /* Byte region(s) per glyph to output
+ unpadded, hints removed if so requested
+ If we fail to process a glyph we produce an empty (0-length) glyph */
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ glyf *glyf_prime = c->serializer->start_embed <glyf> ();
+ if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
+
+ hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
+ _populate_subset_glyphs (c->plan, &glyphs);
+
+ auto padded_offsets =
+ + hb_iter (glyphs)
+ | hb_map (&glyf_impl::SubsetGlyph::padded_size)
+ ;
+
+ unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
+ bool use_short_loca = max_offset < 0x1FFFF;
+
+
+ glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
+ if (!use_short_loca) {
+ padded_offsets =
+ + hb_iter (glyphs)
+ | hb_map (&glyf_impl::SubsetGlyph::length)
+ ;
+ }
+
+
+ if (unlikely (c->serializer->in_error ())) return_trace (false);
+ return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
+ padded_offsets,
+ use_short_loca)));
+ }
+
+ void
+ _populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Glyphs data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+struct glyf_accelerator_t
+{
+ glyf_accelerator_t (hb_face_t *face)
+ {
+ short_offset = false;
+ num_glyphs = 0;
+ loca_table = nullptr;
+ glyf_table = nullptr;
+#ifndef HB_NO_VAR
+ gvar = nullptr;
+#endif
+ hmtx = nullptr;
+#ifndef HB_NO_VERTICAL
+ vmtx = nullptr;
+#endif
+ const OT::head &head = *face->table.head;
+ if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
+ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
+ return;
+ short_offset = 0 == head.indexToLocFormat;
+
+ loca_table = face->table.loca.get_blob (); // Needs no destruct!
+ glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
+#ifndef HB_NO_VAR
+ gvar = face->table.gvar;
+#endif
+ hmtx = face->table.hmtx;
+#ifndef HB_NO_VERTICAL
+ vmtx = face->table.vmtx;
+#endif
+
+ num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+ num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
+ }
+ ~glyf_accelerator_t ()
+ {
+ glyf_table.destroy ();
+ }
+
+ bool has_data () const { return num_glyphs; }
+
+ protected:
+ template<typename T>
+ bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
+ {
+ if (gid >= num_glyphs) return false;
+
+ /* Making this allocfree is not that easy
+ https://github.com/harfbuzz/harfbuzz/issues/2095
+ mostly because of gvar handling in VF fonts,
+ perhaps a separate path for non-VF fonts can be considered */
+ contour_point_vector_t all_points;
+
+ bool phantom_only = !consumer.is_consuming_contour_points ();
+ if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
+ return false;
+
+ if (consumer.is_consuming_contour_points ())
+ {
+ unsigned count = all_points.length;
+ assert (count >= glyf_impl::PHANTOM_COUNT);
+ count -= glyf_impl::PHANTOM_COUNT;
+ for (unsigned point_index = 0; point_index < count; point_index++)
+ consumer.consume_point (all_points[point_index]);
+ consumer.points_end ();
+ }
+
+ /* Where to write phantoms, nullptr if not requested */
+ contour_point_t *phantoms = consumer.get_phantoms_sink ();
+ if (phantoms)
+ for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
+ phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i];
+
+ return true;
+ }
+
+#ifndef HB_NO_VAR
+ struct points_aggregator_t
+ {
+ hb_font_t *font;
+ hb_glyph_extents_t *extents;
+ contour_point_t *phantoms;
+
+ struct contour_bounds_t
+ {
+ contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
+
+ void add (const contour_point_t &p)
+ {
+ min_x = hb_min (min_x, p.x);
+ min_y = hb_min (min_y, p.y);
+ max_x = hb_max (max_x, p.x);
+ max_y = hb_max (max_y, p.y);
+ }
+
+ bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
+
+ void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
+ {
+ if (unlikely (empty ()))
+ {
+ extents->width = 0;
+ extents->x_bearing = 0;
+ extents->height = 0;
+ extents->y_bearing = 0;
+ return;
+ }
+ extents->x_bearing = font->em_scalef_x (min_x);
+ extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
+ extents->y_bearing = font->em_scalef_y (max_y);
+ extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
+ }
+
+ protected:
+ float min_x, min_y, max_x, max_y;
+ } bounds;
+
+ points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
+ {
+ font = font_;
+ extents = extents_;
+ phantoms = phantoms_;
+ if (extents) bounds = contour_bounds_t ();
+ }
+
+ void consume_point (const contour_point_t &point) { bounds.add (point); }
+ void points_end () { bounds.get_extents (font, extents); }
+
+ bool is_consuming_contour_points () { return extents; }
+ contour_point_t *get_phantoms_sink () { return phantoms; }
+ };
+
+ public:
+ unsigned
+ get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
+ {
+ if (unlikely (gid >= num_glyphs)) return 0;
+
+ bool success = false;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (likely (font->num_coords == gvar->get_axis_count ()))
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
+
+ if (unlikely (!success))
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_advance (gid) :
+#endif
+ hmtx->get_advance (gid);
+
+ float result = is_vertical
+ ? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y
+ : phantoms[glyf_impl::PHANTOM_RIGHT].x - phantoms[glyf_impl::PHANTOM_LEFT].x;
+ return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
+ }
+
+ int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
+ {
+ if (unlikely (gid >= num_glyphs)) return 0;
+
+ hb_glyph_extents_t extents;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_side_bearing (gid) :
+#endif
+ hmtx->get_side_bearing (gid);
+
+ return is_vertical
+ ? ceilf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
+ : floorf (phantoms[glyf_impl::PHANTOM_LEFT].x);
+ }
+#endif
+
+ public:
+ bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+#ifndef HB_NO_VAR
+ if (font->num_coords)
+ return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
+#endif
+ return glyph_for_gid (gid).get_extents (font, *this, extents);
+ }
+
+ const glyf_impl::Glyph
+ glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
+ {
+ if (unlikely (gid >= num_glyphs)) return glyf_impl::Glyph ();
+
+ unsigned int start_offset, end_offset;
+
+ if (short_offset)
+ {
+ const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
+ start_offset = 2 * offsets[gid];
+ end_offset = 2 * offsets[gid + 1];
+ }
+ else
+ {
+ const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
+ start_offset = offsets[gid];
+ end_offset = offsets[gid + 1];
+ }
+
+ if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
+ return glyf_impl::Glyph ();
+
+ glyf_impl::Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
+ end_offset - start_offset), gid);
+ return needs_padding_removal ? glyf_impl::Glyph (glyph.trim_padding (), gid) : glyph;
+ }
+
+ bool
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
+
+#ifndef HB_NO_VAR
+ const gvar_accelerator_t *gvar;
+#endif
+ const hmtx_accelerator_t *hmtx;
+#ifndef HB_NO_VERTICAL
+ const vmtx_accelerator_t *vmtx;
+#endif
+
+ private:
+ bool short_offset;
+ unsigned int num_glyphs;
+ hb_blob_ptr_t<loca> loca_table;
+ hb_blob_ptr_t<glyf> glyf_table;
+};
+
+
+inline void
+glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
+{
+ OT::glyf_accelerator_t glyf (plan->source);
+
+ + hb_range (plan->num_output_glyphs ())
+ | hb_map ([&] (hb_codepoint_t new_gid)
+ {
+ glyf_impl::SubsetGlyph subset_glyph = {0};
+ subset_glyph.new_gid = new_gid;
+
+ /* should never fail: all old gids should be mapped */
+ if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
+ return subset_glyph;
+
+ if (new_gid == 0 &&
+ !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ subset_glyph.source_glyph = glyf_impl::Glyph ();
+ else
+ subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ subset_glyph.drop_hints_bytes ();
+ else
+ subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
+ return subset_glyph;
+ })
+ | hb_sink (glyphs)
+ ;
+}
+
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/loca.hh b/thirdparty/harfbuzz/src/OT/glyf/loca.hh
new file mode 100644
index 0000000000..4481cba8ed
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/loca.hh
@@ -0,0 +1,43 @@
+#ifndef OT_GLYF_LOCA_HH
+#define OT_GLYF_LOCA_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+
+
+/*
+ * loca -- Index to Location
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
+ */
+#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+
+struct loca
+{
+ friend struct glyf;
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (true);
+ }
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Location data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_LOCA_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh b/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh
new file mode 100644
index 0000000000..9bfc45a1a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh
@@ -0,0 +1,135 @@
+#ifndef OT_GLYF_PATH_BUILDER_HH
+#define OT_GLYF_PATH_BUILDER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct path_builder_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+
+ struct optional_point_t
+ {
+ optional_point_t () {}
+ optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
+ operator bool () const { return has_data; }
+
+ bool has_data = false;
+ float x = 0.;
+ float y = 0.;
+
+ optional_point_t lerp (optional_point_t p, float t)
+ { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
+ } first_oncurve, first_offcurve, last_offcurve;
+
+ path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
+ {
+ font = font_;
+ draw_session = &draw_session_;
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ }
+
+ /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
+ See also:
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
+ * https://stackoverflow.com/a/20772557 */
+ void consume_point (const contour_point_t &point)
+ {
+ bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
+ optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
+ if (!first_oncurve)
+ {
+ if (is_on_curve)
+ {
+ first_oncurve = p;
+ draw_session->move_to (p.x, p.y);
+ }
+ else
+ {
+ if (first_offcurve)
+ {
+ optional_point_t mid = first_offcurve.lerp (p, .5f);
+ first_oncurve = mid;
+ last_offcurve = p;
+ draw_session->move_to (mid.x, mid.y);
+ }
+ else
+ first_offcurve = p;
+ }
+ }
+ else
+ {
+ if (last_offcurve)
+ {
+ if (is_on_curve)
+ {
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
+ last_offcurve = optional_point_t ();
+ }
+ else
+ {
+ optional_point_t mid = last_offcurve.lerp (p, .5f);
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = p;
+ }
+ }
+ else
+ {
+ if (is_on_curve)
+ draw_session->line_to (p.x, p.y);
+ else
+ last_offcurve = p;
+ }
+ }
+
+ if (point.is_end_point)
+ {
+ if (first_offcurve && last_offcurve)
+ {
+ optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = optional_point_t ();
+ /* now check the rest */
+ }
+
+ if (first_offcurve && first_oncurve)
+ draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else if (last_offcurve && first_oncurve)
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else if (first_oncurve)
+ draw_session->line_to (first_oncurve.x, first_oncurve.y);
+ else if (first_offcurve)
+ {
+ float x = first_offcurve.x, y = first_offcurve.y;
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
+
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ draw_session->close_path ();
+ }
+ }
+ void points_end () {}
+
+ bool is_consuming_contour_points () { return true; }
+ contour_point_t *get_phantoms_sink () { return nullptr; }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_PATH_BUILDER_HH */
diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh
new file mode 100644
index 0000000000..52ca9dd142
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/graph.hh
@@ -0,0 +1,860 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_GRAPH_HH
+#define GRAPH_GRAPH_HH
+
+namespace graph {
+
+/**
+ * Represents a serialized table in the form of a graph.
+ * Provides methods for modifying and reordering the graph.
+ */
+struct graph_t
+{
+ struct vertex_t
+ {
+ hb_serialize_context_t::object_t obj;
+ int64_t distance = 0 ;
+ int64_t space = 0 ;
+ hb_vector_t<unsigned> parents;
+ unsigned start = 0;
+ unsigned end = 0;
+ unsigned priority = 0;
+
+ friend void swap (vertex_t& a, vertex_t& b)
+ {
+ hb_swap (a.obj, b.obj);
+ hb_swap (a.distance, b.distance);
+ hb_swap (a.space, b.space);
+ hb_swap (a.parents, b.parents);
+ hb_swap (a.start, b.start);
+ hb_swap (a.end, b.end);
+ hb_swap (a.priority, b.priority);
+ }
+
+ bool is_shared () const
+ {
+ return parents.length > 1;
+ }
+
+ unsigned incoming_edges () const
+ {
+ return parents.length;
+ }
+
+ void remove_parent (unsigned parent_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] != parent_index) continue;
+ parents.remove (i);
+ break;
+ }
+ }
+
+ void remap_parents (const hb_vector_t<unsigned>& id_map)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ parents[i] = id_map[parents[i]];
+ }
+
+ void remap_parent (unsigned old_index, unsigned new_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] == old_index)
+ parents[i] = new_index;
+ }
+ }
+
+ bool is_leaf () const
+ {
+ return !obj.real_links.length && !obj.virtual_links.length;
+ }
+
+ bool raise_priority ()
+ {
+ if (has_max_priority ()) return false;
+ priority++;
+ return true;
+ }
+
+ bool has_max_priority () const {
+ return priority >= 3;
+ }
+
+ int64_t modified_distance (unsigned order) const
+ {
+ // TODO(garretrieger): once priority is high enough, should try
+ // setting distance = 0 which will force to sort immediately after
+ // it's parent where possible.
+
+ int64_t modified_distance =
+ hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
+ if (has_max_priority ()) {
+ modified_distance = 0;
+ }
+ return (modified_distance << 18) | (0x003FFFF & order);
+ }
+
+ int64_t distance_modifier () const
+ {
+ if (!priority) return 0;
+ int64_t table_size = obj.tail - obj.head;
+
+ if (priority == 1)
+ return -table_size / 2;
+
+ return -table_size;
+ }
+ };
+
+ /*
+ * A topological sorting of an object graph. Ordered
+ * in reverse serialization order (first object in the
+ * serialization is at the end of the list). This matches
+ * the 'packed' object stack used internally in the
+ * serializer
+ */
+ template<typename T>
+ graph_t (const T& objects)
+ : parents_invalid (true),
+ distance_invalid (true),
+ positions_invalid (true),
+ successful (true)
+ {
+ num_roots_for_space_.push (1);
+ bool removed_nil = false;
+ vertices_.alloc (objects.length);
+ vertices_scratch_.alloc (objects.length);
+ for (unsigned i = 0; i < objects.length; i++)
+ {
+ // TODO(grieger): check all links point to valid objects.
+
+ // If this graph came from a serialization buffer object 0 is the
+ // nil object. We don't need it for our purposes here so drop it.
+ if (i == 0 && !objects[i])
+ {
+ removed_nil = true;
+ continue;
+ }
+
+ vertex_t* v = vertices_.push ();
+ if (check_success (!vertices_.in_error ()))
+ v->obj = *objects[i];
+ if (!removed_nil) continue;
+ // Fix indices to account for removed nil object.
+ for (auto& l : v->obj.all_links_writer ()) {
+ l.objidx--;
+ }
+ }
+ }
+
+ ~graph_t ()
+ {
+ vertices_.fini ();
+ }
+
+ bool in_error () const
+ {
+ return !successful ||
+ vertices_.in_error () ||
+ num_roots_for_space_.in_error ();
+ }
+
+ const vertex_t& root () const
+ {
+ return vertices_[root_idx ()];
+ }
+
+ unsigned root_idx () const
+ {
+ // Object graphs are in reverse order, the first object is at the end
+ // of the vector. Since the graph is topologically sorted it's safe to
+ // assume the first object has no incoming edges.
+ return vertices_.length - 1;
+ }
+
+ const hb_serialize_context_t::object_t& object(unsigned i) const
+ {
+ return vertices_[i].obj;
+ }
+
+ /*
+ * Generates a new topological sorting of graph ordered by the shortest
+ * distance to each node.
+ */
+ void sort_shortest_distance ()
+ {
+ positions_invalid = true;
+
+ if (vertices_.length <= 1) {
+ // Graph of 1 or less doesn't need sorting.
+ return;
+ }
+
+ update_distances ();
+
+ hb_priority_queue_t queue;
+ hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
+ if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
+ hb_vector_t<unsigned> id_map;
+ if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
+
+ hb_vector_t<unsigned> removed_edges;
+ if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
+ update_parents ();
+
+ queue.insert (root ().modified_distance (0), root_idx ());
+ int new_id = root_idx ();
+ unsigned order = 1;
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_id = queue.pop_minimum().second;
+
+ hb_swap (sorted_graph[new_id], vertices_[next_id]);
+ const vertex_t& next = sorted_graph[new_id];
+
+ id_map[next_id] = new_id--;
+
+ for (const auto& link : next.obj.all_links ()) {
+ removed_edges[link.objidx]++;
+ if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
+ // Add the order that the links were encountered to the priority.
+ // This ensures that ties between priorities objects are broken in a consistent
+ // way. More specifically this is set up so that if a set of objects have the same
+ // distance they'll be added to the topological order in the order that they are
+ // referenced from the parent object.
+ queue.insert (vertices_[link.objidx].modified_distance (order++),
+ link.objidx);
+ }
+ }
+
+ check_success (!queue.in_error ());
+ check_success (!sorted_graph.in_error ());
+ if (!check_success (new_id == -1))
+ print_orphaned_nodes ();
+
+ remap_all_obj_indices (id_map, &sorted_graph);
+
+ hb_swap (vertices_, sorted_graph);
+ }
+
+ /*
+ * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
+ */
+ bool assign_32bit_spaces ()
+ {
+ unsigned root_index = root_idx ();
+ hb_set_t visited;
+ hb_set_t roots;
+ for (unsigned i = 0; i <= root_index; i++)
+ {
+ // Only real links can form 32 bit spaces
+ for (auto& l : vertices_[i].obj.real_links)
+ {
+ if (l.width == 4 && !l.is_signed)
+ {
+ roots.add (l.objidx);
+ find_subgraph (l.objidx, visited);
+ }
+ }
+ }
+
+ // Mark everything not in the subgraphs of 32 bit roots as visited.
+ // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
+ visited.invert ();
+
+ if (!roots) return false;
+
+ while (roots)
+ {
+ unsigned next = HB_SET_VALUE_INVALID;
+ if (unlikely (!check_success (!roots.in_error ()))) break;
+ if (!roots.next (&next)) break;
+
+ hb_set_t connected_roots;
+ find_connected_nodes (next, roots, visited, connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ isolate_subgraph (connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ unsigned next_space = this->next_space ();
+ num_roots_for_space_.push (0);
+ for (unsigned root : connected_roots)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
+ vertices_[root].space = next_space;
+ num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+
+ // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
+ // into the 32 bit space as needed, instead of using isolation.
+ }
+
+
+
+ return true;
+ }
+
+ /*
+ * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
+ * that originate from outside of the subgraph will be removed by duplicating the linked to
+ * object.
+ *
+ * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
+ */
+ bool isolate_subgraph (hb_set_t& roots)
+ {
+ update_parents ();
+ hb_map_t subgraph;
+
+ // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
+ // set the subgraph incoming edge count to match all of root_idx's incoming edges
+ hb_set_t parents;
+ for (unsigned root_idx : roots)
+ {
+ subgraph.set (root_idx, wide_parents (root_idx, parents));
+ find_subgraph (root_idx, subgraph);
+ }
+
+ unsigned original_root_idx = root_idx ();
+ hb_map_t index_map;
+ bool made_changes = false;
+ for (auto entry : subgraph.iter ())
+ {
+ const auto& node = vertices_[entry.first];
+ unsigned subgraph_incoming_edges = entry.second;
+
+ if (subgraph_incoming_edges < node.incoming_edges ())
+ {
+ // Only de-dup objects with incoming links from outside the subgraph.
+ made_changes = true;
+ duplicate_subgraph (entry.first, index_map);
+ }
+ }
+
+ if (!made_changes)
+ return false;
+
+ if (original_root_idx != root_idx ()
+ && parents.has (original_root_idx))
+ {
+ // If the root idx has changed since parents was determined, update root idx in parents
+ parents.add (root_idx ());
+ parents.del (original_root_idx);
+ }
+
+ auto new_subgraph =
+ + subgraph.keys ()
+ | hb_map([&] (unsigned node_idx) {
+ const unsigned *v;
+ if (index_map.has (node_idx, &v)) return *v;
+ return node_idx;
+ })
+ ;
+
+ remap_obj_indices (index_map, new_subgraph);
+ remap_obj_indices (index_map, parents.iter (), true);
+
+ // Update roots set with new indices as needed.
+ unsigned next = HB_SET_VALUE_INVALID;
+ while (roots.next (&next))
+ {
+ const unsigned *v;
+ if (index_map.has (next, &v))
+ {
+ roots.del (next);
+ roots.add (*v);
+ }
+ }
+
+ return true;
+ }
+
+ void find_subgraph (unsigned node_idx, hb_map_t& subgraph)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ const unsigned *v;
+ if (subgraph.has (link.objidx, &v))
+ {
+ subgraph.set (link.objidx, *v + 1);
+ continue;
+ }
+ subgraph.set (link.objidx, 1);
+ find_subgraph (link.objidx, subgraph);
+ }
+ }
+
+ void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
+ {
+ if (subgraph.has (node_idx)) return;
+ subgraph.add (node_idx);
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ find_subgraph (link.objidx, subgraph);
+ }
+
+ /*
+ * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
+ * links. index_map is updated with mappings from old id to new id. If a duplication has already
+ * been performed for a given index, then it will be skipped.
+ */
+ void duplicate_subgraph (unsigned node_idx, hb_map_t& index_map)
+ {
+ if (index_map.has (node_idx))
+ return;
+
+ index_map.set (node_idx, duplicate (node_idx));
+ for (const auto& l : object (node_idx).all_links ()) {
+ duplicate_subgraph (l.objidx, index_map);
+ }
+ }
+
+ /*
+ * Creates a copy of node_idx and returns it's new index.
+ */
+ unsigned duplicate (unsigned node_idx)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ auto& child = vertices_[node_idx];
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = child.obj.head;
+ clone->obj.tail = child.obj.tail;
+ clone->distance = child.distance;
+ clone->space = child.space;
+ clone->parents.reset ();
+
+ unsigned clone_idx = vertices_.length - 2;
+ for (const auto& l : child.obj.real_links)
+ {
+ clone->obj.real_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+ for (const auto& l : child.obj.virtual_links)
+ {
+ clone->obj.virtual_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+
+ check_success (!clone->obj.real_links.in_error ());
+ check_success (!clone->obj.virtual_links.in_error ());
+
+ // The last object is the root of the graph, so swap back the root to the end.
+ // The root's obj idx does change, however since it's root nothing else refers to it.
+ // all other obj idx's will be unaffected.
+ hb_swap (vertices_[vertices_.length - 2], *clone);
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root ().obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Creates a copy of child and re-assigns the link from
+ * parent to the clone. The copy is a shallow copy, objects
+ * linked from child are not duplicated.
+ */
+ bool duplicate (unsigned parent_idx, unsigned child_idx)
+ {
+ update_parents ();
+
+ unsigned links_to_child = 0;
+ for (const auto& l : vertices_[parent_idx].obj.all_links ())
+ {
+ if (l.objidx == child_idx) links_to_child++;
+ }
+
+ if (vertices_[child_idx].incoming_edges () <= links_to_child)
+ {
+ // Can't duplicate this node, doing so would orphan the original one as all remaining links
+ // to child are from parent.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
+ parent_idx, child_idx);
+ return false;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
+ parent_idx, child_idx);
+
+ unsigned clone_idx = duplicate (child_idx);
+ if (clone_idx == (unsigned) -1) return false;
+ // duplicate shifts the root node idx, so if parent_idx was root update it.
+ if (parent_idx == clone_idx) parent_idx++;
+
+ auto& parent = vertices_[parent_idx];
+ for (auto& l : parent.obj.all_links_writer ())
+ {
+ if (l.objidx != child_idx)
+ continue;
+
+ reassign_link (l, parent_idx, clone_idx);
+ }
+
+ return true;
+ }
+
+ /*
+ * Raises the sorting priority of all children.
+ */
+ bool raise_childrens_priority (unsigned parent_idx)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
+ parent_idx);
+ // This operation doesn't change ordering until a sort is run, so no need
+ // to invalidate positions. It does not change graph structure so no need
+ // to update distances or edge counts.
+ auto& parent = vertices_[parent_idx].obj;
+ bool made_change = false;
+ for (auto& l : parent.all_links_writer ())
+ made_change |= vertices_[l.objidx].raise_priority ();
+ return made_change;
+ }
+
+ void print_orphaned_nodes ()
+ {
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ parents_invalid = true;
+ update_parents();
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ const auto& v = vertices_[i];
+ if (!v.parents)
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
+ }
+ }
+
+ unsigned num_roots_for_space (unsigned space) const
+ {
+ return num_roots_for_space_[space];
+ }
+
+ unsigned next_space () const
+ {
+ return num_roots_for_space_.length;
+ }
+
+ void move_to_new_space (const hb_set_t& indices)
+ {
+ num_roots_for_space_.push (0);
+ unsigned new_space = num_roots_for_space_.length - 1;
+
+ for (unsigned index : indices) {
+ auto& node = vertices_[index];
+ num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
+ num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
+ node.space = new_space;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+ }
+
+ unsigned space_for (unsigned index, unsigned* root = nullptr) const
+ {
+ const auto& node = vertices_[index];
+ if (node.space)
+ {
+ if (root != nullptr)
+ *root = index;
+ return node.space;
+ }
+
+ if (!node.parents)
+ {
+ if (root)
+ *root = index;
+ return 0;
+ }
+
+ return space_for (node.parents[0], root);
+ }
+
+ void err_other_error () { this->successful = false; }
+
+ size_t total_size_in_bytes () const {
+ size_t total_size = 0;
+ for (unsigned i = 0; i < vertices_.length; i++) {
+ size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
+ total_size += size;
+ }
+ return total_size;
+ }
+
+
+ private:
+
+ /*
+ * Returns the numbers of incoming edges that are 32bits wide.
+ */
+ unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
+ {
+ unsigned count = 0;
+ hb_set_t visited;
+ for (unsigned p : vertices_[node_idx].parents)
+ {
+ if (visited.has (p)) continue;
+ visited.add (p);
+
+ // Only real links can be wide
+ for (const auto& l : vertices_[p].obj.real_links)
+ {
+ if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
+ {
+ count++;
+ parents.add (p);
+ }
+ }
+ }
+ return count;
+ }
+
+ bool check_success (bool success)
+ { return this->successful && (success || ((void) err_other_error (), false)); }
+
+ public:
+ /*
+ * Creates a map from objid to # of incoming edges.
+ */
+ void update_parents ()
+ {
+ if (!parents_invalid) return;
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ vertices_[i].parents.reset ();
+
+ for (unsigned p = 0; p < vertices_.length; p++)
+ {
+ for (auto& l : vertices_[p].obj.all_links ())
+ {
+ vertices_[l.objidx].parents.push (p);
+ }
+ }
+
+ parents_invalid = false;
+ }
+
+ /*
+ * compute the serialized start and end positions for each vertex.
+ */
+ void update_positions ()
+ {
+ if (!positions_invalid) return;
+
+ unsigned current_pos = 0;
+ for (int i = root_idx (); i >= 0; i--)
+ {
+ auto& v = vertices_[i];
+ v.start = current_pos;
+ current_pos += v.obj.tail - v.obj.head;
+ v.end = current_pos;
+ }
+
+ positions_invalid = false;
+ }
+
+ /*
+ * Finds the distance to each object in the graph
+ * from the initial node.
+ */
+ void update_distances ()
+ {
+ if (!distance_invalid) return;
+
+ // Uses Dijkstra's algorithm to find all of the shortest distances.
+ // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+ //
+ // Implementation Note:
+ // Since our priority queue doesn't support fast priority decreases
+ // we instead just add new entries into the queue when a priority changes.
+ // Redundant ones are filtered out later on by the visited set.
+ // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
+ // for practical performance this is faster then using a more advanced queue
+ // (such as a fibonacci queue) with a fast decrease priority.
+ for (unsigned i = 0; i < vertices_.length; i++)
+ {
+ if (i == vertices_.length - 1)
+ vertices_[i].distance = 0;
+ else
+ vertices_[i].distance = hb_int_max (int64_t);
+ }
+
+ hb_priority_queue_t queue;
+ queue.insert (0, vertices_.length - 1);
+
+ hb_vector_t<bool> visited;
+ visited.resize (vertices_.length);
+
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_idx = queue.pop_minimum ().second;
+ if (visited[next_idx]) continue;
+ const auto& next = vertices_[next_idx];
+ int64_t next_distance = vertices_[next_idx].distance;
+ visited[next_idx] = true;
+
+ for (const auto& link : next.obj.all_links ())
+ {
+ if (visited[link.objidx]) continue;
+
+ const auto& child = vertices_[link.objidx].obj;
+ unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
+ int64_t child_weight = (child.tail - child.head) +
+ ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
+ int64_t child_distance = next_distance + child_weight;
+
+ if (child_distance < vertices_[link.objidx].distance)
+ {
+ vertices_[link.objidx].distance = child_distance;
+ queue.insert (child_distance, link.objidx);
+ }
+ }
+ }
+
+ check_success (!queue.in_error ());
+ if (!check_success (queue.is_empty ()))
+ {
+ print_orphaned_nodes ();
+ return;
+ }
+
+ distance_invalid = false;
+ }
+
+ private:
+ /*
+ * Updates a link in the graph to point to a different object. Corrects the
+ * parents vector on the previous and new child nodes.
+ */
+ void reassign_link (hb_serialize_context_t::object_t::link_t& link,
+ unsigned parent_idx,
+ unsigned new_idx)
+ {
+ unsigned old_idx = link.objidx;
+ link.objidx = new_idx;
+ vertices_[old_idx].remove_parent (parent_idx);
+ vertices_[new_idx].parents.push (parent_idx);
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
+ */
+ template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
+ void remap_obj_indices (const hb_map_t& id_map,
+ Iterator subgraph,
+ bool only_wide = false)
+ {
+ if (!id_map) return;
+ for (unsigned i : subgraph)
+ {
+ for (auto& link : vertices_[i].obj.all_links_writer ())
+ {
+ const unsigned *v;
+ if (!id_map.has (link.objidx, &v)) continue;
+ if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
+
+ reassign_link (link, i, *v);
+ }
+ }
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping.
+ */
+ void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
+ hb_vector_t<vertex_t>* sorted_graph) const
+ {
+ for (unsigned i = 0; i < sorted_graph->length; i++)
+ {
+ (*sorted_graph)[i].remap_parents (id_map);
+ for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
+ {
+ link.objidx = id_map[link.objidx];
+ }
+ }
+ }
+
+ /*
+ * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
+ * For this search the graph is treated as being undirected.
+ *
+ * Connected targets will be added to connected and removed from targets. All visited nodes
+ * will be added to visited.
+ */
+ void find_connected_nodes (unsigned start_idx,
+ hb_set_t& targets,
+ hb_set_t& visited,
+ hb_set_t& connected)
+ {
+ if (unlikely (!check_success (!visited.in_error ()))) return;
+ if (visited.has (start_idx)) return;
+ visited.add (start_idx);
+
+ if (targets.has (start_idx))
+ {
+ targets.del (start_idx);
+ connected.add (start_idx);
+ }
+
+ const auto& v = vertices_[start_idx];
+
+ // Graph is treated as undirected so search children and parents of start_idx
+ for (const auto& l : v.obj.all_links ())
+ find_connected_nodes (l.objidx, targets, visited, connected);
+
+ for (unsigned p : v.parents)
+ find_connected_nodes (p, targets, visited, connected);
+ }
+
+ public:
+ // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
+ hb_vector_t<vertex_t> vertices_;
+ hb_vector_t<vertex_t> vertices_scratch_;
+ private:
+ bool parents_invalid;
+ bool distance_invalid;
+ bool positions_invalid;
+ bool successful;
+ hb_vector_t<unsigned> num_roots_for_space_;
+};
+
+}
+
+#endif // GRAPH_GRAPH_HH
diff --git a/thirdparty/harfbuzz/src/graph/serialize.hh b/thirdparty/harfbuzz/src/graph/serialize.hh
new file mode 100644
index 0000000000..ecc6cc5aea
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/serialize.hh
@@ -0,0 +1,249 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_SERIALIZE_HH
+#define GRAPH_SERIALIZE_HH
+
+namespace graph {
+
+struct overflow_record_t
+{
+ unsigned parent;
+ unsigned child;
+};
+
+inline
+int64_t compute_offset (
+ const graph_t& graph,
+ unsigned parent_idx,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ const auto& parent = graph.vertices_[parent_idx];
+ const auto& child = graph.vertices_[link.objidx];
+ int64_t offset = 0;
+ switch ((hb_serialize_context_t::whence_t) link.whence) {
+ case hb_serialize_context_t::whence_t::Head:
+ offset = child.start - parent.start; break;
+ case hb_serialize_context_t::whence_t::Tail:
+ offset = child.start - parent.end; break;
+ case hb_serialize_context_t::whence_t::Absolute:
+ offset = child.start; break;
+ }
+
+ assert (offset >= link.bias);
+ offset -= link.bias;
+ return offset;
+}
+
+inline
+bool is_valid_offset (int64_t offset,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ if (unlikely (!link.width))
+ // Virtual links can't overflow.
+ return link.is_signed || offset >= 0;
+
+ if (link.is_signed)
+ {
+ if (link.width == 4)
+ return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
+ else
+ return offset >= -(1 << 15) && offset < (1 << 15);
+ }
+ else
+ {
+ if (link.width == 4)
+ return offset >= 0 && offset < ((int64_t) 1 << 32);
+ else if (link.width == 3)
+ return offset >= 0 && offset < ((int32_t) 1 << 24);
+ else
+ return offset >= 0 && offset < (1 << 16);
+ }
+}
+
+/*
+ * Will any offsets overflow on graph when it's serialized?
+ */
+inline bool
+will_overflow (graph_t& graph,
+ hb_vector_t<overflow_record_t>* overflows = nullptr)
+{
+ if (overflows) overflows->resize (0);
+ graph.update_positions ();
+
+ const auto& vertices = graph.vertices_;
+ for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
+ {
+ // Don't need to check virtual links for overflow
+ for (const auto& link : vertices[parent_idx].obj.real_links)
+ {
+ int64_t offset = compute_offset (graph, parent_idx, link);
+ if (is_valid_offset (offset, link))
+ continue;
+
+ if (!overflows) return true;
+
+ overflow_record_t r;
+ r.parent = parent_idx;
+ r.child = link.objidx;
+ overflows->push (r);
+ }
+ }
+
+ if (!overflows) return false;
+ return overflows->length;
+}
+
+inline
+void print_overflows (graph_t& graph,
+ const hb_vector_t<overflow_record_t>& overflows)
+{
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ graph.update_parents ();
+ int limit = 10;
+ for (const auto& o : overflows)
+ {
+ if (!limit--) break;
+ const auto& parent = graph.vertices_[o.parent];
+ const auto& child = graph.vertices_[o.child];
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " overflow from "
+ "%4d (%4d in, %4d out, space %2d) => "
+ "%4d (%4d in, %4d out, space %2d)",
+ o.parent,
+ parent.incoming_edges (),
+ parent.obj.real_links.length + parent.obj.virtual_links.length,
+ graph.space_for (o.parent),
+ o.child,
+ child.incoming_edges (),
+ child.obj.real_links.length + child.obj.virtual_links.length,
+ graph.space_for (o.child));
+ }
+ if (overflows.length > 10) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
+ }
+}
+
+template <typename O> inline void
+serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
+ *offset = 0;
+ c->add_link (*offset,
+ // serializer has an extra nil object at the start of the
+ // object array. So all id's are +1 of what our id's are.
+ link.objidx + 1,
+ (hb_serialize_context_t::whence_t) link.whence,
+ link.bias);
+}
+
+inline
+void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ switch (link.width)
+ {
+ case 0:
+ // Virtual links aren't serialized.
+ return;
+ case 4:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT32> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT32> (link, head, c);
+ }
+ return;
+ case 2:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT16> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT16> (link, head, c);
+ }
+ return;
+ case 3:
+ serialize_link_of_type<OT::HBUINT24> (link, head, c);
+ return;
+ default:
+ // Unexpected link width.
+ assert (0);
+ }
+}
+
+/*
+ * serialize graph into the provided serialization buffer.
+ */
+inline hb_blob_t* serialize (const graph_t& graph)
+{
+ hb_vector_t<char> buffer;
+ size_t size = graph.total_size_in_bytes ();
+ if (!buffer.alloc (size)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
+ return nullptr;
+ }
+ hb_serialize_context_t c((void *) buffer, size);
+
+ c.start_serialize<void> ();
+ const auto& vertices = graph.vertices_;
+ for (unsigned i = 0; i < vertices.length; i++) {
+ c.push ();
+
+ size_t size = vertices[i].obj.tail - vertices[i].obj.head;
+ char* start = c.allocate_size <char> (size);
+ if (!start) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
+ return nullptr;
+ }
+
+ memcpy (start, vertices[i].obj.head, size);
+
+ // Only real links needs to be serialized.
+ for (const auto& link : vertices[i].obj.real_links)
+ serialize_link (link, start, &c);
+
+ // All duplications are already encoded in the graph, so don't
+ // enable sharing during packing.
+ c.pop_pack (false);
+ }
+ c.end_serialize ();
+
+ if (c.in_error ()) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
+ c.errors);
+ return nullptr;
+ }
+
+ return c.copy_blob ();
+}
+
+} // namespace graph
+
+#endif // GRAPH_SERIALIZE_HH
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
index 0354b47d5a..6a24c90c31 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
@@ -287,7 +287,7 @@ struct KerxSubTableFormat1
* in the 'kern' table example. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.y_offset = 0;
}
@@ -310,7 +310,7 @@ struct KerxSubTableFormat1
/* CoreText doesn't do crossStream kerning in vertical. We do. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.x_offset = 0;
}
@@ -567,7 +567,7 @@ struct KerxSubTableFormat4
}
break;
}
- o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_MARK;
o.attach_chain() = (int) mark - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
@@ -901,7 +901,7 @@ struct KerxTable
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[i].attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_CURSIVE;
pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
/* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
* since there needs to be a non-zero attachment for post-positioning to
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
index b77c1f4d44..3d053cb13e 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -123,7 +123,7 @@ struct RearrangementSubtable
bool reverse_l = 3 == (m >> 4);
bool reverse_r = 3 == (m & 0x0F);
- if (end - start >= l + r)
+ if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH)
{
buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
buffer->merge_clusters (start, end);
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index 05b4df52f1..f1633d886a 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -59,7 +59,7 @@
static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
- static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
+ static inline constexpr unsigned operator ~ (T r) { return (~(unsigned) r); } \
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
@@ -227,31 +227,26 @@ struct
}
HB_FUNCOBJ (hb_bool);
-template <typename T>
-static inline
-constexpr T hb_coerce (const T v) { return v; }
-template <typename T, typename V,
- hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
-static inline
-constexpr T hb_coerce (const V v) { return *v; }
-
struct
{
private:
template <typename T> constexpr auto
- impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
- template <typename T> constexpr auto
- impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
+ template <typename T> constexpr uint32_t
+ impl (const hb::shared_ptr<T>& v, hb_priority<1>) const
+ {
+ return v.get () ? v.get ()->hash () : 0;
+ }
+ template <typename T> constexpr uint32_t
+ impl (const hb::unique_ptr<T>& v, hb_priority<1>) const
+ {
+ return v.get () ? v.get ()->hash () : 0;
+ }
- template <typename T,
- hb_enable_if (std::is_integral<T>::value)> constexpr auto
- impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
- (
- /* Knuth's multiplicative method: */
- (uint32_t) v * 2654435761u
- )
+ template <typename T> constexpr auto
+ impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
public:
@@ -862,6 +857,11 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
{
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4)
+{
+ return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3) || hb_in_range (u, lo4, hi4);
+}
/*
diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh
index 1963698cf7..5baeb6f7fe 100644
--- a/thirdparty/harfbuzz/src/hb-array.hh
+++ b/thirdparty/harfbuzz/src/hb-array.hh
@@ -56,7 +56,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_array_t& operator= (const hb_array_t&) = default;
hb_array_t& operator= (hb_array_t&&) = default;
- constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_>
constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
@@ -314,7 +313,6 @@ struct hb_sorted_array_t :
hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
- constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_>
constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
diff --git a/thirdparty/harfbuzz/src/hb-bimap.hh b/thirdparty/harfbuzz/src/hb-bimap.hh
index 5b313bf59c..8e8c988716 100644
--- a/thirdparty/harfbuzz/src/hb-bimap.hh
+++ b/thirdparty/harfbuzz/src/hb-bimap.hh
@@ -54,17 +54,18 @@ struct hb_bimap_t
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
forw_map.set (lhs, rhs);
- if (in_error ()) return;
+ if (unlikely (in_error ())) return;
back_map.set (rhs, lhs);
- if (in_error ()) forw_map.del (lhs);
+ if (unlikely (in_error ())) forw_map.del (lhs);
}
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
- bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
+ bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
+
void del (hb_codepoint_t lhs)
{
@@ -78,7 +79,7 @@ struct hb_bimap_t
back_map.clear ();
}
- bool is_empty () const { return get_population () == 0; }
+ bool is_empty () const { return forw_map.is_empty (); }
unsigned int get_population () const { return forw_map.get_population (); }
diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
index caea47d8d3..27fb0732ea 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
@@ -80,7 +80,7 @@ struct hb_bit_set_invertible_t
next (&v);
return v == INVALID;
}
- uint32_t hash () const { return s.hash () ^ inverted; }
+ uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; }
hb_codepoint_t get_min () const
{
@@ -100,7 +100,7 @@ struct hb_bit_set_invertible_t
void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
- { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
+ { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); }
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh
index 11a4359dc9..438fb66a2c 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set.hh
@@ -56,7 +56,7 @@ struct hb_bit_set_t
{
successful = true;
population = 0;
- last_page_lookup = 0;
+ last_page_lookup.set_relaxed (0);
page_map.init ();
pages.init ();
}
@@ -78,7 +78,7 @@ struct hb_bit_set_t
bool successful = true; /* Allocations successful */
mutable unsigned int population = 0;
- mutable unsigned int last_page_lookup = 0;
+ mutable hb_atomic_int_t last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages;
@@ -607,7 +607,7 @@ struct hb_bit_set_t
const auto* page_map_array = page_map.arrayZ;
unsigned int major = get_major (*codepoint);
- unsigned int i = last_page_lookup;
+ unsigned int i = last_page_lookup.get_relaxed ();
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
{
@@ -625,7 +625,7 @@ struct hb_bit_set_t
if (pages_array[current.index].next (codepoint))
{
*codepoint += current.major * page_t::PAGE_BITS;
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return true;
}
i++;
@@ -638,11 +638,11 @@ struct hb_bit_set_t
if (m != INVALID)
{
*codepoint = current.major * page_t::PAGE_BITS + m;
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return true;
}
}
- last_page_lookup = 0;
+ last_page_lookup.set_relaxed (0);
*codepoint = INVALID;
return false;
}
@@ -725,7 +725,7 @@ struct hb_bit_set_t
{
const auto* page_map_array = page_map.arrayZ;
unsigned int major = get_major (codepoint);
- unsigned int i = last_page_lookup;
+ unsigned int i = last_page_lookup.get_relaxed ();
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
{
page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
@@ -766,7 +766,7 @@ struct hb_bit_set_t
{
const auto* page_map_array = page_map.arrayZ;
unsigned int major = get_major (codepoint);
- unsigned int i = last_page_lookup;
+ unsigned int i = last_page_lookup.get_relaxed ();
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
{
page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST);
@@ -893,15 +893,15 @@ struct hb_bit_set_t
/* The extra page_map length is necessary; can't just rely on vector here,
* since the next check would be tricked because a null page also has
* major==0, which we can't distinguish from an actualy major==0 page... */
- if (likely (last_page_lookup < page_map.length))
+ unsigned i = last_page_lookup.get_relaxed ();
+ if (likely (i < page_map.length))
{
- auto &cached_page = page_map.arrayZ[last_page_lookup];
+ auto &cached_page = page_map.arrayZ[i];
if (cached_page.major == major)
return &pages[cached_page.index];
}
page_map_t map = {major, pages.length};
- unsigned int i;
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
{
if (!insert)
@@ -917,7 +917,7 @@ struct hb_bit_set_t
page_map[i] = map;
}
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return &pages[page_map[i].index];
}
const page_t *page_for (hb_codepoint_t g) const
@@ -927,19 +927,19 @@ struct hb_bit_set_t
/* The extra page_map length is necessary; can't just rely on vector here,
* since the next check would be tricked because a null page also has
* major==0, which we can't distinguish from an actualy major==0 page... */
- if (likely (last_page_lookup < page_map.length))
+ unsigned i = last_page_lookup.get_relaxed ();
+ if (likely (i < page_map.length))
{
- auto &cached_page = page_map.arrayZ[last_page_lookup];
+ auto &cached_page = page_map.arrayZ[i];
if (cached_page.major == major)
return &pages[cached_page.index];
}
page_map_t key = {major};
- unsigned int i;
if (!page_map.bfind (key, &i))
return nullptr;
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return &pages[page_map[i].index];
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc
index 65e44c7f6a..b561a9374e 100644
--- a/thirdparty/harfbuzz/src/hb-blob.cc
+++ b/thirdparty/harfbuzz/src/hb-blob.cc
@@ -369,7 +369,7 @@ hb_blob_get_length (hb_blob_t *blob)
*
* Fetches the data from a blob.
*
- * Returns: (transfer none) (array length=length): the byte data of @blob.
+ * Returns: (nullable) (transfer none) (array length=length): the byte data of @blob.
*
* Since: 0.9.2
**/
@@ -572,7 +572,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
strncpy (rsrc_name, file_name, name_len);
strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC,
- sizeof (_PATH_RSRCFORKSPEC) - 1);
+ sizeof (_PATH_RSRCFORKSPEC));
int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
hb_free (rsrc_name);
diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
index 6539b89640..3f619a113e 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
@@ -31,7 +31,7 @@
#include "hb-buffer.hh"
-static const char *serialize_formats[] = {
+static const char *_hb_buffer_serialize_formats[] = {
"text",
"json",
nullptr
@@ -50,7 +50,7 @@ static const char *serialize_formats[] = {
const char **
hb_buffer_serialize_list_formats ()
{
- return serialize_formats;
+ return _hb_buffer_serialize_formats;
}
/**
@@ -91,8 +91,8 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
{
switch ((unsigned) format)
{
- case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
- case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
+ case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return _hb_buffer_serialize_formats[0];
+ case HB_BUFFER_SERIALIZE_FORMAT_JSON: return _hb_buffer_serialize_formats[1];
default:
case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
}
@@ -400,9 +400,9 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If %NULL, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -514,7 +514,7 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -637,9 +637,9 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If %NULL, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
index dea2c11c35..5453e1ca94 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-verify.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
@@ -102,9 +102,9 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
/* Check that breaking up shaping at safe-to-break is indeed safe. */
hb_buffer_t *fragment = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (fragment, hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragment, (hb_buffer_flags_t (hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY)));
hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
unsigned int num_glyphs;
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
@@ -169,6 +169,12 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
hb_buffer_destroy (fragment);
return false;
}
+ else if (!fragment->successful || fragment->shaping_failed)
+ {
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return true;
+ }
hb_buffer_append (reconstruction, fragment, 0, -1);
start = end;
@@ -238,10 +244,10 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer),
hb_buffer_create_similar (buffer)};
- hb_buffer_set_flags (fragments[0], hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY);
- hb_buffer_set_flags (fragments[1], hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragments[0], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_buffer_set_flags (fragments[1], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY)));
hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
- hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
hb_segment_properties_t props;
hb_buffer_get_segment_properties (buffer, &props);
hb_buffer_set_segment_properties (fragments[0], &props);
@@ -317,12 +323,22 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
ret = false;
goto out;
}
+ else if (!fragments[0]->successful || fragments[0]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
{
buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
ret = false;
goto out;
}
+ else if (!fragments[1]->successful || fragments[1]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
if (!forward)
{
@@ -402,6 +418,7 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
ret = false;
if (!ret)
{
+#ifndef HB_NO_BUFFER_SERIALIZE
unsigned len = text_buffer->len;
hb_vector_t<char> bytes;
if (likely (bytes.resize (len * 10 + 16)))
@@ -414,6 +431,7 @@ hb_buffer_t::verify (hb_buffer_t *text_buffer,
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
}
+#endif
}
return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index 6a9ee3ccc8..2272ecf09b 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -81,8 +81,8 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p)
{
- return (unsigned int) p->direction ^
- (unsigned int) p->script ^
+ return ((unsigned int) p->direction * 31 +
+ (unsigned int) p->script) * 31 +
(intptr_t) (p->language);
}
@@ -289,6 +289,7 @@ hb_buffer_t::clear ()
props = default_props;
successful = true;
+ shaping_failed = false;
have_output = false;
have_positions = false;
@@ -310,6 +311,7 @@ hb_buffer_t::enter ()
{
deallocate_var_all ();
serial = 0;
+ shaping_failed = false;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
{
@@ -329,6 +331,7 @@ hb_buffer_t::leave ()
max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
deallocate_var_all ();
serial = 0;
+ // Intentionally not reseting shaping_failed, such that it can be inspected.
}
@@ -542,7 +545,8 @@ hb_buffer_t::delete_glyph ()
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
unsigned int cluster = info[idx].cluster;
- if (idx + 1 < len && cluster == info[idx + 1].cluster)
+ if ((idx + 1 < len && cluster == info[idx + 1].cluster) ||
+ (out_len && cluster == out_info[out_len - 1].cluster))
{
/* Cluster survives; do nothing. */
goto done;
@@ -623,6 +627,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
+ true, /* shaping_failed */
false, /* have_output */
true /* have_positions */
@@ -631,7 +636,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
/**
- * hb_buffer_create: (Xconstructor)
+ * hb_buffer_create:
*
* Creates a new #hb_buffer_t with all properties to defaults.
*
@@ -834,7 +839,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
* Since: 0.9.5
**/
hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer)
+hb_buffer_get_content_type (const hb_buffer_t *buffer)
{
return buffer->content_type;
}
@@ -876,7 +881,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer)
{
return buffer->unicode;
}
@@ -919,7 +924,7 @@ hb_buffer_set_direction (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer)
+hb_buffer_get_direction (const hb_buffer_t *buffer)
{
return buffer->props.direction;
}
@@ -963,7 +968,7 @@ hb_buffer_set_script (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
+hb_buffer_get_script (const hb_buffer_t *buffer)
{
return buffer->props.script;
}
@@ -1007,7 +1012,7 @@ hb_buffer_set_language (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
+hb_buffer_get_language (const hb_buffer_t *buffer)
{
return buffer->props.language;
}
@@ -1043,7 +1048,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
* Since: 0.9.7
**/
void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props)
{
*props = buffer->props;
@@ -1081,7 +1086,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
* Since: 0.9.7
**/
hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer)
+hb_buffer_get_flags (const hb_buffer_t *buffer)
{
return buffer->flags;
}
@@ -1120,7 +1125,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
* Since: 0.9.42
**/
hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer)
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer)
{
return buffer->cluster_level;
}
@@ -1161,7 +1166,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
* Since: 0.9.31
**/
hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer)
{
return buffer->replacement;
}
@@ -1201,7 +1206,7 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
* Since: 2.0.0
**/
hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer)
{
return buffer->invisible;
}
@@ -1241,7 +1246,7 @@ hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
* Since: 3.1.0
**/
hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer)
{
return buffer->not_found;
}
@@ -1381,7 +1386,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
* Since: 0.9.2
**/
unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer)
+hb_buffer_get_length (const hb_buffer_t *buffer)
{
return buffer->len;
}
diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h
index 14aaa5e1f5..22fb3496f2 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.h
+++ b/thirdparty/harfbuzz/src/hb-buffer.h
@@ -289,7 +289,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
hb_buffer_content_type_t content_type);
HB_EXTERN hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer);
+hb_buffer_get_content_type (const hb_buffer_t *buffer);
HB_EXTERN void
@@ -297,21 +297,21 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
hb_unicode_funcs_t *unicode_funcs);
HB_EXTERN hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer);
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction);
HB_EXTERN hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer);
+hb_buffer_get_direction (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_script (hb_buffer_t *buffer,
hb_script_t script);
HB_EXTERN hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer);
+hb_buffer_get_script (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_language (hb_buffer_t *buffer,
@@ -319,14 +319,14 @@ hb_buffer_set_language (hb_buffer_t *buffer,
HB_EXTERN hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer);
+hb_buffer_get_language (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_segment_properties (hb_buffer_t *buffer,
const hb_segment_properties_t *props);
HB_EXTERN void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props);
HB_EXTERN void
@@ -373,6 +373,7 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
* glyph-flag should be produced by the shaper. By default
* it will not be produced since it incurs a cost. Since: 4.0.0
+ * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0
*
* Flags for #hb_buffer_t.
*
@@ -386,7 +387,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
HB_BUFFER_FLAG_VERIFY = 0x00000020u,
- HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u,
+
+ HB_BUFFER_FLAG_DEFINED = 0x0000007Fu
} hb_buffer_flags_t;
HB_EXTERN void
@@ -394,7 +397,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags);
HB_EXTERN hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer);
+hb_buffer_get_flags (const hb_buffer_t *buffer);
/**
* hb_buffer_cluster_level_t:
@@ -436,7 +439,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
HB_EXTERN hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer);
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer);
/**
* HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
@@ -453,21 +456,21 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
hb_codepoint_t replacement);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
hb_codepoint_t invisible);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
hb_codepoint_t not_found);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer);
/*
@@ -549,7 +552,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
unsigned int length);
HB_EXTERN unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer);
+hb_buffer_get_length (const hb_buffer_t *buffer);
/* Getting glyphs out of the buffer */
@@ -583,6 +586,7 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
* @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
* glyph offsets will reflect absolute glyph positions. Since: 1.8.0
+ * @HB_BUFFER_SERIALIZE_FLAG_DEFINED: All currently defined flags. Since: 4.4.0
*
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
*
@@ -595,7 +599,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u,
- HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u
+ HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u,
+
+ HB_BUFFER_SERIALIZE_FLAG_DEFINED = 0x0000003Fu
} hb_buffer_serialize_flags_t;
/**
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index bc6992905e..6ca78f28d4 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer.hh
@@ -57,6 +57,7 @@
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
+HB_MARK_AS_FLAG_T (hb_glyph_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
@@ -69,12 +70,13 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u,
- /* Reserved for complex shapers' internal use. */
- HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u,
+ /* Reserved for shapers' internal use. */
+ HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER1 = 0x02000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER2 = 0x04000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER3 = 0x08000000u,
};
HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
@@ -106,6 +108,7 @@ struct hb_buffer_t
hb_segment_properties_t props; /* Script, language, direction */
bool successful; /* Allocations successful */
+ bool shaping_failed; /* Shaping failure */
bool have_output; /* Whether we have an output buffer going on */
bool have_positions; /* Whether we have positions */
@@ -130,9 +133,7 @@ struct hb_buffer_t
* Managed by enter / leave
*/
-#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
-#endif
uint8_t serial;
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
unsigned int max_len; /* Maximum allowed len. */
@@ -161,38 +162,40 @@ struct hb_buffer_t
void allocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (0 == (allocated_var_bits & bits));
allocated_var_bits |= bits;
-#endif
+ }
+ bool try_allocate_var (unsigned int start, unsigned int count)
+ {
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1u<<end) - (1u<<start);
+ if (allocated_var_bits & bits)
+ return false;
+ allocated_var_bits |= bits;
+ return true;
}
void deallocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
allocated_var_bits &= ~bits;
-#endif
}
void assert_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
- unsigned int bits = (1u<<end) - (1u<<start);
+ HB_UNUSED unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
-#endif
}
void deallocate_var_all ()
{
-#ifndef HB_NDEBUG
allocated_var_bits = 0;
-#endif
}
hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
@@ -549,7 +552,7 @@ struct hb_buffer_t
#ifdef HB_NO_BUFFER_MESSAGE
return true;
#else
- if (!messaging ())
+ if (likely (!messaging ()))
return true;
message_depth++;
@@ -619,9 +622,10 @@ DECLARE_NULL_INSTANCE (hb_buffer_t);
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
+#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
+#define HB_BUFFER_TRY_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
#endif /* HB_BUFFER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-cache.hh b/thirdparty/harfbuzz/src/hb-cache.hh
index e617b75de9..d6b229ed65 100644
--- a/thirdparty/harfbuzz/src/hb-cache.hh
+++ b/thirdparty/harfbuzz/src/hb-cache.hh
@@ -32,7 +32,7 @@
/* Implements a lockfree cache for int->int functions. */
-template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+template <unsigned int key_bits=16, unsigned int value_bits=8 + 32 - key_bits, unsigned int cache_bits=8>
struct hb_cache_t
{
static_assert ((key_bits >= cache_bits), "");
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index 41229b9183..7266d9b01f 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -160,7 +160,7 @@ hb_tag_to_string (hb_tag_t tag, char *buf)
/* hb_direction_t */
-const char direction_strings[][4] = {
+static const char direction_strings[][4] = {
"ltr",
"rtl",
"ttb",
diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh
index 4b46dea938..2578231d23 100644
--- a/thirdparty/harfbuzz/src/hb-config.hh
+++ b/thirdparty/harfbuzz/src/hb-config.hh
@@ -64,6 +64,7 @@
#define HB_NO_FACE_COLLECT_UNICODES
#define HB_NO_GETENV
#define HB_NO_HINTING
+#define HB_NO_LANGUAGE_LONG
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
#define HB_NO_LAYOUT_FEATURE_PARAMS
#define HB_NO_LAYOUT_COLLECT_GLYPHS
@@ -145,10 +146,10 @@
#endif
#ifdef HB_NO_OT_SHAPE_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_ARABIC_FALLBACK
+#define HB_NO_OT_SHAPER_HEBREW_FALLBACK
+#define HB_NO_OT_SHAPER_THAI_FALLBACK
+#define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
#endif
#ifdef NDEBUG
@@ -163,5 +164,9 @@
#endif
#endif
+#ifdef HB_OPTIMIZE_SIZE
+#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
+#endif
+
#endif /* HB_CONFIG_HH */
diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc
index 6ccc1b0a2b..99b33c001e 100644
--- a/thirdparty/harfbuzz/src/hb-coretext.cc
+++ b/thirdparty/harfbuzz/src/hb-coretext.cc
@@ -332,7 +332,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return nullptr;
}
- if (font->coords)
+ if (font->num_coords)
{
CFMutableDictionaryRef variations =
CFDictionaryCreateMutable (kCFAllocatorDefault,
@@ -379,37 +379,6 @@ _hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
CFRelease ((CTFontRef) data);
}
-static const hb_coretext_font_data_t *
-hb_coretext_font_data_sync (hb_font_t *font)
-{
-retry:
- const hb_coretext_font_data_t *data = font->data.coretext;
- if (unlikely (!data)) return nullptr;
-
- if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5)
- {
- /* XXX-MT-bug
- * Note that evaluating condition above can be dangerous if another thread
- * got here first and destructed data. That's, as always, bad use pattern.
- * If you modify the font (change font size), other threads must not be
- * using it at the same time. However, since this check is delayed to
- * when one actually tries to shape something, this is a XXX race condition
- * (and the only one we have that I know of) right now. Ie. you modify the
- * font size in one thread, then (supposedly safely) try to use it from two
- * or more threads and BOOM! I'm not sure how to fix this. We want RCU.
- */
-
- /* Drop and recreate. */
- /* If someone dropped it in the mean time, throw it away and don't touch it.
- * Otherwise, destruct it. */
- if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
- _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
- else
- goto retry;
- }
- return font->data.coretext;
-}
-
/**
* hb_coretext_font_create:
* @ct_font: The CTFontRef to work upon
@@ -455,8 +424,8 @@ hb_coretext_font_create (CTFontRef ct_font)
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
- const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
- return data ? (CTFontRef) data : nullptr;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+ return ct_font ? (CTFontRef) ct_font : nullptr;
}
@@ -516,7 +485,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
hb_face_t *face = font->face;
CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
- CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -1106,7 +1075,8 @@ resize_and_retry:
advance = positions[j + 1].x - positions[j].x;
else /* last glyph */
advance = run_advance - (positions[j].x - positions[0].x);
- info->mask = round (advance * x_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * x_mult);
info->var1.i32 = x_offset;
info->var2.i32 = round (positions[j].y * y_mult);
info++;
@@ -1122,7 +1092,8 @@ resize_and_retry:
advance = positions[j + 1].y - positions[j].y;
else /* last glyph */
advance = run_advance - (positions[j].y - positions[0].y);
- info->mask = round (advance * y_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * y_mult);
info->var1.i32 = round (positions[j].x * x_mult);
info->var2.i32 = y_offset;
info++;
@@ -1151,7 +1122,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
else
for (unsigned int i = 0; i < count; i++)
@@ -1160,7 +1131,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
/* Fix up clusters so that we never return out-of-order indices;
@@ -1173,7 +1144,8 @@ resize_and_retry:
* This does *not* mean we'll form the same clusters as Uniscribe
* or the native OT backend, only that the cluster indices will be
* monotonic in the output buffer. */
- if (count > 1 && (status_or & kCTRunStatusNonMonotonic))
+ if (count > 1 && (status_or & kCTRunStatusNonMonotonic) &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
{
hb_glyph_info_t *info = buffer->info;
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
@@ -1197,6 +1169,10 @@ resize_and_retry:
}
}
+ /* TODO: Sometimes the above positioning code generates negative
+ * advance values. Fix them up. Example, with NotoNastaliqUrdu
+ * font and sequence ابهد. */
+
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh
new file mode 100644
index 0000000000..86d0452080
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh
@@ -0,0 +1,192 @@
+/*
+ * Copyright © 2022 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_CPLUSPLUS_HH
+#define HB_CPLUSPLUS_HH
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+HB_END_DECLS
+
+#ifdef __cplusplus
+
+#include <functional>
+#include <utility>
+
+#if 0
+#if !(__cplusplus >= 201103L)
+#error "HarfBuzz C++ helpers require C++11"
+#endif
+#endif
+
+namespace hb {
+
+
+template <typename T>
+struct vtable;
+
+template <typename T>
+struct shared_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit shared_ptr (T *p = nullptr) : p (p) {}
+ shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {}
+ shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; }
+ shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; }
+ shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~shared_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+
+ void swap (shared_ptr &o) { std::swap (p, o.p); }
+ friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () { return p; }
+ bool operator == (const shared_ptr &o) { return p == o.p; }
+ bool operator != (const shared_ptr &o) { return p != o.p; }
+
+ static T* get_empty() { return v::get_empty (); }
+ T* reference() { return v::reference (p); }
+ void destroy() { v::destroy (p); }
+ void set_user_data (hb_user_data_key_t *key,
+ void *value,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace) { v::set_user_data (p, key, value, destroy, replace); }
+ void * get_user_data (hb_user_data_key_t *key) { return v::get_user_data (p, key); }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_shared_ptr : std::false_type {};
+template<typename T> struct is_shared_ptr<shared_ptr<T>> : std::true_type {};
+
+template <typename T>
+struct unique_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit unique_ptr (T *p = nullptr) : p (p) {}
+ unique_ptr (const unique_ptr &o) = delete;
+ unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; }
+ unique_ptr& operator = (const unique_ptr &o) = delete;
+ unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~unique_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+ T* release () { T* v = p; p = nullptr; return v; }
+
+ void swap (unique_ptr &o) { std::swap (p, o.p); }
+ friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () { return p; }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_unique_ptr : std::false_type {};
+template<typename T> struct is_unique_ptr<unique_ptr<T>> : std::true_type {};
+
+template <typename T,
+ T * (*_get_empty) (void),
+ T * (*_reference) (T *),
+ void (*_destroy) (T *),
+ hb_bool_t (*_set_user_data) (T *,
+ hb_user_data_key_t *,
+ void *,
+ hb_destroy_func_t,
+ hb_bool_t),
+ void * (*_get_user_data) (T *,
+ hb_user_data_key_t *)>
+struct vtable_t
+{
+ static constexpr auto get_empty = _get_empty;
+ static constexpr auto reference = _reference;
+ static constexpr auto destroy = _destroy;
+ static constexpr auto set_user_data = _set_user_data;
+ static constexpr auto get_user_data = _get_user_data;
+};
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ &hb_##name##_get_empty, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+HB_DEFINE_VTABLE (buffer);
+HB_DEFINE_VTABLE (blob);
+HB_DEFINE_VTABLE (face);
+HB_DEFINE_VTABLE (font);
+HB_DEFINE_VTABLE (font_funcs);
+HB_DEFINE_VTABLE (map);
+HB_DEFINE_VTABLE (set);
+HB_DEFINE_VTABLE (shape_plan);
+HB_DEFINE_VTABLE (unicode_funcs);
+
+#undef HB_DEFINE_VTABLE
+
+
+} // namespace hb
+
+template<typename T>
+struct std::hash<hb::shared_ptr<T>>
+{
+ std::size_t operator()(const hb::shared_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+template<typename T>
+struct std::hash<hb::unique_ptr<T>>
+{
+ std::size_t operator()(const hb::unique_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+
+#endif /* __cplusplus */
+
+#endif /* HB_CPLUSPLUS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc
index f177ff31c0..ce04f5bab1 100644
--- a/thirdparty/harfbuzz/src/hb-directwrite.cc
+++ b/thirdparty/harfbuzz/src/hb-directwrite.cc
@@ -241,17 +241,12 @@ struct hb_directwrite_font_data_t {};
hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
- hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
- if (unlikely (!data))
- return nullptr;
-
- return data;
+ return (hb_directwrite_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
- delete data;
}
diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc
index b31019b07e..fdc71102d6 100644
--- a/thirdparty/harfbuzz/src/hb-draw.cc
+++ b/thirdparty/harfbuzz/src/hb-draw.cc
@@ -56,12 +56,14 @@ hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
float to_x, float to_y,
void *user_data HB_UNUSED)
{
+#define HB_ONE_THIRD 0.33333333f
dfuncs->emit_cubic_to (draw_data, *st,
- (st->current_x + 2.f * control_x) / 3.f,
- (st->current_y + 2.f * control_y) / 3.f,
- (to_x + 2.f * control_x) / 3.f,
- (to_y + 2.f * control_y) / 3.f,
+ (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
+ (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
+ (to_x + 2.f * control_x) * HB_ONE_THIRD,
+ (to_y + 2.f * control_y) * HB_ONE_THIRD,
to_x, to_y);
+#undef HB_ONE_THIRD
}
static void
@@ -89,25 +91,46 @@ hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
if (hb_object_is_immutable (dfuncs)) \
return; \
\
- if (dfuncs->destroy.name) \
- dfuncs->destroy.name (dfuncs->user_data.name); \
- \
- if (func) { \
- dfuncs->func.name = func; \
- dfuncs->user_data.name = user_data; \
- dfuncs->destroy.name = destroy; \
- } else { \
- dfuncs->func.name = hb_draw_##name##_nil; \
- dfuncs->user_data.name = nullptr; \
- dfuncs->destroy.name = nullptr; \
- } \
+ if (dfuncs->destroy && dfuncs->destroy->name) \
+ dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
+ \
+ if (user_data && !dfuncs->user_data) \
+ { \
+ dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); \
+ if (unlikely (!dfuncs->user_data)) \
+ goto fail; \
+ } \
+ if (destroy && !dfuncs->destroy) \
+ { \
+ dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); \
+ if (unlikely (!dfuncs->destroy)) \
+ goto fail; \
+ } \
+ \
+ if (func) { \
+ dfuncs->func.name = func; \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = user_data; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = destroy; \
+ } else { \
+ dfuncs->func.name = hb_draw_##name##_nil; \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = nullptr; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = nullptr; \
+ } \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
}
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
/**
- * hb_draw_funcs_create: (Xconstructor)
+ * hb_draw_funcs_create:
*
* Creates a new draw callbacks object.
*
@@ -177,11 +200,13 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
if (!hb_object_destroy (dfuncs)) return;
+ if (dfuncs->destroy)
+ {
#define HB_DRAW_FUNC_IMPLEMENT(name) \
- if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
- HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+ if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
-
+ }
hb_free (dfuncs);
}
diff --git a/thirdparty/harfbuzz/src/hb-draw.hh b/thirdparty/harfbuzz/src/hb-draw.hh
index 28bc9218e1..768f51a875 100644
--- a/thirdparty/harfbuzz/src/hb-draw.hh
+++ b/thirdparty/harfbuzz/src/hb-draw.hh
@@ -54,31 +54,31 @@ struct hb_draw_funcs_t
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
- } user_data;
+ } *user_data;
struct {
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_DRAW_FUNC_IMPLEMENT
- } destroy;
+ } *destroy;
void emit_move_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.move_to (this, draw_data, &st,
to_x, to_y,
- user_data.move_to); }
+ !user_data ? nullptr : user_data->move_to); }
void emit_line_to (void *draw_data, hb_draw_state_t &st,
float to_x, float to_y)
{ func.line_to (this, draw_data, &st,
to_x, to_y,
- user_data.line_to); }
+ !user_data ? nullptr : user_data->line_to); }
void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
float control_x, float control_y,
float to_x, float to_y)
{ func.quadratic_to (this, draw_data, &st,
control_x, control_y,
to_x, to_y,
- user_data.quadratic_to); }
+ !user_data ? nullptr : user_data->quadratic_to); }
void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
float control1_x, float control1_y,
float control2_x, float control2_y,
@@ -87,10 +87,10 @@ struct hb_draw_funcs_t
control1_x, control1_y,
control2_x, control2_y,
to_x, to_y,
- user_data.cubic_to); }
+ !user_data ? nullptr : user_data->cubic_to); }
void emit_close_path (void *draw_data, hb_draw_state_t &st)
{ func.close_path (this, draw_data, &st,
- user_data.close_path); }
+ !user_data ? nullptr : user_data->close_path); }
void move_to (void *draw_data, hb_draw_state_t &st,
diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc
index 5365598636..7cdd6cb49f 100644
--- a/thirdparty/harfbuzz/src/hb-face.cc
+++ b/thirdparty/harfbuzz/src/hb-face.cc
@@ -190,7 +190,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
}
/**
- * hb_face_create: (Xconstructor)
+ * hb_face_create:
* @blob: #hb_blob_t to work upon
* @index: The index of the face within @blob
*
@@ -342,7 +342,7 @@ hb_face_set_user_data (hb_face_t *face,
* Since: 0.9.2
**/
void *
-hb_face_get_user_data (const hb_face_t *face,
+hb_face_get_user_data (hb_face_t *face,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (face, key);
diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h
index 6ef2f8b886..3b7477a76c 100644
--- a/thirdparty/harfbuzz/src/hb-face.h
+++ b/thirdparty/harfbuzz/src/hb-face.h
@@ -96,7 +96,7 @@ hb_face_set_user_data (hb_face_t *face,
hb_bool_t replace);
HB_EXTERN void *
-hb_face_get_user_data (const hb_face_t *face,
+hb_face_get_user_data (hb_face_t *face,
hb_user_data_key_t *key);
HB_EXTERN void
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 5700e06271..8c4fe863b6 100644
--- a/thirdparty/harfbuzz/src/hb-font.cc
+++ b/thirdparty/harfbuzz/src/hb-font.cc
@@ -636,16 +636,8 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+ nullptr,
+ nullptr,
{
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
@@ -658,16 +650,8 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
static const hb_font_funcs_t _hb_font_funcs_default = {
HB_OBJECT_HEADER_STATIC,
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+ nullptr,
+ nullptr,
{
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
@@ -679,7 +663,7 @@ static const hb_font_funcs_t _hb_font_funcs_default = {
/**
- * hb_font_funcs_create: (Xconstructor)
+ * hb_font_funcs_create:
*
* Creates a new #hb_font_funcs_t structure of font functions.
*
@@ -746,10 +730,16 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
{
if (!hb_object_destroy (ffuncs)) return;
-#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name);
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+ if (ffuncs->destroy)
+ {
+#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy->name) \
+ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name);
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
+ }
+
+ hb_free (ffuncs->destroy);
+ hb_free (ffuncs->user_data);
hb_free (ffuncs);
}
@@ -841,24 +831,50 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (ffuncs)) \
+ goto fail; \
+ \
+ if (!func) \
{ \
if (destroy) \
destroy (user_data); \
- return; \
+ destroy = nullptr; \
+ user_data = nullptr; \
} \
\
- if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name); \
+ if (ffuncs->destroy && ffuncs->destroy->name) \
+ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \
+ \
+ if (user_data && !ffuncs->user_data) \
+ { \
+ ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); \
+ if (unlikely (!ffuncs->user_data)) \
+ goto fail; \
+ } \
+ if (destroy && !ffuncs->destroy) \
+ { \
+ ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); \
+ if (unlikely (!ffuncs->destroy)) \
+ goto fail; \
+ } \
\
if (func) { \
ffuncs->get.f.name = func; \
- ffuncs->user_data.name = user_data; \
- ffuncs->destroy.name = destroy; \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = user_data; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = destroy; \
} else { \
ffuncs->get.f.name = hb_font_get_##name##_default; \
- ffuncs->user_data.name = nullptr; \
- ffuncs->destroy.name = nullptr; \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = nullptr; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = nullptr; \
} \
+ return; \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
}
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -1623,6 +1639,9 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
{
HB_OBJECT_HEADER_STATIC,
+ 0, /* serial */
+ 0, /* serial_coords */
+
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
@@ -1630,6 +1649,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* y_scale */
0., /* slant */
0., /* slant_xy; */
+ 1.f, /* x_multf */
+ 1.f, /* y_multf */
1<<16, /* x_mult */
1<<16, /* y_mult */
@@ -1662,14 +1683,15 @@ _hb_font_create (hb_face_t *face)
font->face = hb_face_reference (face);
font->klass = hb_font_funcs_get_empty ();
font->data.init0 (font);
- font->x_scale = font->y_scale = hb_face_get_upem (face);
+ font->x_scale = font->y_scale = face->get_upem ();
+ font->x_multf = font->y_multf = 1.f;
font->x_mult = font->y_mult = 1 << 16;
return font;
}
/**
- * hb_font_create: (Xconstructor)
+ * hb_font_create:
* @face: a face.
*
* Constructs a new font object from the specified face.
@@ -1715,6 +1737,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
font->coords = coords;
font->design_coords = design_coords;
font->num_coords = coords_length;
+
+ font->mults_changed (); // Easiest to call this to drop cached data
}
/**
@@ -1744,7 +1768,6 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_scale = parent->x_scale;
font->y_scale = parent->y_scale;
font->slant = parent->slant;
- font->mults_changed ();
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
font->ptem = parent->ptem;
@@ -1767,6 +1790,8 @@ hb_font_create_sub_font (hb_font_t *parent)
}
}
+ font->mults_changed ();
+
return font;
}
@@ -1852,6 +1877,9 @@ hb_font_set_user_data (hb_font_t *font,
hb_destroy_func_t destroy /* May be NULL. */,
hb_bool_t replace)
{
+ if (!hb_object_is_immutable (font))
+ font->serial++;
+
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@@ -1911,6 +1939,45 @@ hb_font_is_immutable (hb_font_t *font)
}
/**
+ * hb_font_get_serial:
+ * @font: #hb_font_t to work upon
+ *
+ * Returns the internal serial number of the font. The serial
+ * number is increased every time a setting on the font is
+ * changed, using a setter function.
+ *
+ * Return value: serial number
+ *
+ * Since: 4.4.0.
+ **/
+unsigned int
+hb_font_get_serial (hb_font_t *font)
+{
+ return font->serial;
+}
+
+/**
+ * hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Notifies the @font that underlying font data has changed.
+ * This has the effect of increasing the serial as returned
+ * by hb_font_get_serial(), which invalidates internal caches.
+ *
+ * Since: 4.4.0.
+ **/
+void
+hb_font_changed (hb_font_t *font)
+{
+ if (hb_object_is_immutable (font))
+ return;
+
+ font->serial++;
+
+ font->mults_changed ();
+}
+
+/**
* hb_font_set_parent:
* @font: #hb_font_t to work upon
* @parent: The parent font object to assign
@@ -1926,6 +1993,11 @@ hb_font_set_parent (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (parent == font->parent)
+ return;
+
+ font->serial++;
+
if (!parent)
parent = hb_font_get_empty ();
@@ -1968,6 +2040,11 @@ hb_font_set_face (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (face == font->face)
+ return;
+
+ font->serial++;
+
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -2022,6 +2099,8 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2059,6 +2138,8 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -2085,6 +2166,11 @@ hb_font_set_scale (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_scale == x_scale && font->y_scale == y_scale)
+ return;
+
+ font->serial++;
+
font->x_scale = x_scale;
font->y_scale = y_scale;
font->mults_changed ();
@@ -2127,6 +2213,11 @@ hb_font_set_ppem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
+ return;
+
+ font->serial++;
+
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
}
@@ -2169,6 +2260,11 @@ hb_font_set_ptem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->ptem == ptem)
+ return;
+
+ font->serial++;
+
font->ptem = ptem;
}
@@ -2216,6 +2312,11 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
if (hb_object_is_immutable (font))
return;
+ if (font->slant == slant)
+ return;
+
+ font->serial++;
+
font->slant = slant;
font->mults_changed ();
}
@@ -2263,6 +2364,8 @@ hb_font_set_variations (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
if (!variations_length)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
@@ -2322,6 +2425,8 @@ hb_font_set_var_coords_design (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2355,6 +2460,8 @@ hb_font_set_var_named_instance (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2391,6 +2498,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h
index 9548857535..ca6ecf7963 100644
--- a/thirdparty/harfbuzz/src/hb-font.h
+++ b/thirdparty/harfbuzz/src/hb-font.h
@@ -1002,6 +1002,12 @@ hb_font_make_immutable (hb_font_t *font);
HB_EXTERN hb_bool_t
hb_font_is_immutable (hb_font_t *font);
+HB_EXTERN unsigned int
+hb_font_get_serial (hb_font_t *font);
+
+HB_EXTERN void
+hb_font_changed (hb_font_t *font);
+
HB_EXTERN void
hb_font_set_parent (hb_font_t *font,
hb_font_t *parent);
diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh
index 70311b4a85..bb402e23eb 100644
--- a/thirdparty/harfbuzz/src/hb-font.hh
+++ b/thirdparty/harfbuzz/src/hb-font.hh
@@ -68,13 +68,13 @@ struct hb_font_funcs_t
#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
- } user_data;
+ } *user_data;
struct {
#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
- } destroy;
+ } *destroy;
/* Don't access these directly. Call font->get_*() instead. */
union get_t {
@@ -104,6 +104,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
+ unsigned int serial;
+ unsigned int serial_coords;
hb_font_t *parent;
hb_face_t *face;
@@ -112,6 +114,8 @@ struct hb_font_t
int32_t y_scale;
float slant;
float slant_xy;
+ float x_multf;
+ float y_multf;
int64_t x_mult;
int64_t y_mult;
@@ -137,12 +141,12 @@ struct hb_font_t
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
- hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
- hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
- float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
- float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
- float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
- float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
+ hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
+ hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
+ float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
+ float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
+ float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
+ float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@@ -205,14 +209,14 @@ struct hb_font_t
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data,
extents,
- klass->user_data.font_h_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_h_extents);
}
hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
{
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data,
extents,
- klass->user_data.font_v_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_v_extents);
}
bool has_glyph (hb_codepoint_t unicode)
@@ -228,7 +232,7 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.nominal_glyph (this, user_data,
unicode, glyph,
- klass->user_data.nominal_glyph);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
}
unsigned int get_nominal_glyphs (unsigned int count,
const hb_codepoint_t *first_unicode,
@@ -240,7 +244,7 @@ struct hb_font_t
count,
first_unicode, unicode_stride,
first_glyph, glyph_stride,
- klass->user_data.nominal_glyphs);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
}
hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
@@ -250,21 +254,21 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.variation_glyph (this, user_data,
unicode, variation_selector, glyph,
- klass->user_data.variation_glyph);
+ !klass->user_data ? nullptr : klass->user_data->variation_glyph);
}
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_h_advance (this, user_data,
glyph,
- klass->user_data.glyph_h_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
}
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_v_advance (this, user_data,
glyph,
- klass->user_data.glyph_v_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
}
void get_glyph_h_advances (unsigned int count,
@@ -277,7 +281,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_h_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
}
void get_glyph_v_advances (unsigned int count,
@@ -290,7 +294,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_v_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
}
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
@@ -299,7 +303,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_h_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_h_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
}
hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
@@ -308,7 +312,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_v_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_v_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
}
hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
@@ -319,7 +323,7 @@ struct hb_font_t
#else
return klass->get.f.glyph_h_kerning (this, user_data,
left_glyph, right_glyph,
- klass->user_data.glyph_h_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
#endif
}
@@ -331,7 +335,7 @@ struct hb_font_t
#else
return klass->get.f.glyph_v_kerning (this, user_data,
top_glyph, bottom_glyph,
- klass->user_data.glyph_v_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
#endif
}
@@ -342,7 +346,7 @@ struct hb_font_t
return klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
- klass->user_data.glyph_extents);
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
}
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
@@ -352,7 +356,7 @@ struct hb_font_t
return klass->get.f.glyph_contour_point (this, user_data,
glyph, point_index,
x, y,
- klass->user_data.glyph_contour_point);
+ !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
}
hb_bool_t get_glyph_name (hb_codepoint_t glyph,
@@ -362,7 +366,7 @@ struct hb_font_t
return klass->get.f.glyph_name (this, user_data,
glyph,
name, size,
- klass->user_data.glyph_name);
+ !klass->user_data ? nullptr : klass->user_data->glyph_name);
}
hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
@@ -373,7 +377,7 @@ struct hb_font_t
return klass->get.f.glyph_from_name (this, user_data,
name, len,
glyph,
- klass->user_data.glyph_from_name);
+ !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
}
void get_glyph_shape (hb_codepoint_t glyph,
@@ -382,7 +386,7 @@ struct hb_font_t
klass->get.f.glyph_shape (this, user_data,
glyph,
draw_funcs, draw_data,
- klass->user_data.glyph_shape);
+ !klass->user_data ? nullptr : klass->user_data->glyph_shape);
}
@@ -444,7 +448,6 @@ struct hb_font_t
{
*x = get_glyph_h_advance (glyph) / 2;
- /* TODO cache this somehow?! */
hb_font_extents_t extents;
get_h_extents_with_fallback (&extents);
*y = extents.ascender;
@@ -628,20 +631,26 @@ struct hb_font_t
void mults_changed ()
{
- signed upem = face->get_upem ();
- x_mult = ((int64_t) x_scale << 16) / upem;
- y_mult = ((int64_t) y_scale << 16) / upem;
+ float upem = face->get_upem ();
+ x_multf = x_scale / upem;
+ y_multf = y_scale / upem;
+ bool x_neg = x_scale < 0;
+ x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
+ bool y_neg = y_scale < 0;
+ y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
+
+ data.fini ();
}
hb_position_t em_mult (int16_t v, int64_t mult)
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
- hb_position_t em_scalef (float v, int scale)
- { return (hb_position_t) roundf (em_fscalef (v, scale)); }
- float em_fscalef (float v, int scale)
- { return v * scale / face->get_upem (); }
- float em_fscale (int16_t v, int scale)
- { return (float) v * scale / face->get_upem (); }
+ hb_position_t em_multf (float v, float mult)
+ { return (hb_position_t) roundf (em_fmultf (v, mult)); }
+ float em_fmultf (float v, float mult)
+ { return v * mult; }
+ float em_fmult (int16_t v, float mult)
+ { return (float) v * mult; }
};
DECLARE_NULL_INSTANCE (hb_font_t);
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index d3c5d3db93..b526a82865 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -37,6 +37,8 @@
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-shaper-arabic-pua.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
@@ -86,7 +88,7 @@ struct hb_ft_font_t
mutable hb_mutex_t lock;
FT_Face ft_face;
- mutable int cached_x_scale;
+ mutable unsigned cached_serial;
mutable hb_advance_cache_t advance_cache;
};
@@ -103,7 +105,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_x_scale = 0;
+ ft_font->cached_serial = (unsigned) -1;
ft_font->advance_cache.init ();
return ft_font;
@@ -130,6 +132,58 @@ _hb_ft_font_destroy (void *data)
hb_free (ft_font);
}
+
+/* hb_font changed, update FT_Face. */
+static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
+{
+
+ FT_Set_Char_Size (ft_face,
+ abs (font->x_scale), abs (font->y_scale),
+ 0, 0);
+#if 0
+ font->x_ppem * 72 * 64 / font->x_scale,
+ font->y_ppem * 72 * 64 / font->y_scale);
+#endif
+ if (font->x_scale < 0 || font->y_scale < 0)
+ {
+ FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
+ 0, font->y_scale < 0 ? -1 : +1};
+ FT_Set_Transform (ft_face, &matrix, nullptr);
+ }
+
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
+ unsigned int num_coords;
+ const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+ if (num_coords)
+ {
+ FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
+ if (ft_coords)
+ {
+ for (unsigned int i = 0; i < num_coords; i++)
+ ft_coords[i] = coords[i] * 4;
+ FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
+ hb_free (ft_coords);
+ }
+ }
+#endif
+}
+
+/* Check if hb_font changed, update FT_Face. */
+static inline bool
+_hb_ft_hb_font_check_changed (hb_font_t *font,
+ const hb_ft_font_t *ft_font)
+{
+ if (font->serial != ft_font->cached_serial)
+ {
+ _hb_ft_hb_font_changed (font, ft_font->ft_face);
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+ return true;
+ }
+ return false;
+}
+
+
/**
* hb_ft_font_set_load_flags:
* @font: #hb_font_t to work upon
@@ -181,7 +235,7 @@ hb_ft_font_get_load_flags (hb_font_t *font)
}
/**
- * hb_ft_font_get_face:
+ * hb_ft_font_get_face: (skip)
* @font: #hb_font_t to work upon
*
* Fetches the FT_Face associated with the specified #hb_font_t
@@ -203,7 +257,7 @@ hb_ft_font_get_face (hb_font_t *font)
}
/**
- * hb_ft_font_lock_face:
+ * hb_ft_font_lock_face: (skip)
* @font: #hb_font_t to work upon
*
* Gets the FT_Face associated with @font, This face will be kept around until
@@ -246,7 +300,7 @@ hb_ft_font_unlock_face (hb_font_t *font)
static hb_bool_t
-hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+hb_ft_get_nominal_glyph (hb_font_t *font,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
@@ -258,14 +312,29 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
if (unlikely (!g))
{
- if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
+ if (unlikely (ft_font->symbol))
{
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ switch ((unsigned) font->face->table.OS2->get_font_page ()) {
+ case OT::OS2::font_page_t::FONT_PAGE_NONE:
+ if (unicode <= 0x00FFu)
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode));
+ break;
+ case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode));
+ break;
+#endif
+ default:
+ break;
+ }
if (!g)
return false;
}
@@ -337,12 +406,6 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
int load_flags = ft_font->load_flags;
int mult = font->x_scale < 0 ? -1 : +1;
- if (font->x_scale != ft_font->cached_x_scale)
- {
- ft_font->advance_cache.clear ();
- ft_font->cached_x_scale = font->x_scale;
- }
-
for (unsigned int i = 0; i < count; i++)
{
FT_Fixed v = 0;
@@ -426,6 +489,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
@@ -556,6 +620,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
+
metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
@@ -619,6 +684,8 @@ hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
+ _hb_ft_hb_font_check_changed (font, ft_font);
+
if (unlikely (FT_Load_Glyph (ft_face, glyph,
FT_LOAD_NO_BITMAP | ft_font->load_flags)))
return;
@@ -964,6 +1031,31 @@ hb_ft_font_changed (hb_font_t *font)
}
/**
+ * hb_ft_hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Refreshes the state of the underlying FT_Face of @font when the hb_font_t
+ * @font has changed.
+ * This function should be called after changing the size or
+ * variation-axis settings on the @font.
+ * This call is fast if nothing has changed on @font.
+ *
+ * Return value: true if changed, false otherwise
+ *
+ * Since: 4.4.0
+ **/
+hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font)
+{
+ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ return false;
+
+ hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+
+ return _hb_ft_hb_font_check_changed (font, ft_font);
+}
+
+/**
* hb_ft_font_create_referenced:
* @ft_face: FT_Face to work upon
*
@@ -1081,35 +1173,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
- FT_Set_Char_Size (ft_face,
- abs (font->x_scale), abs (font->y_scale),
- 0, 0);
-#if 0
- font->x_ppem * 72 * 64 / font->x_scale,
- font->y_ppem * 72 * 64 / font->y_scale);
-#endif
- if (font->x_scale < 0 || font->y_scale < 0)
- {
- FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
- 0, font->y_scale < 0 ? -1 : +1};
- FT_Set_Transform (ft_face, &matrix, nullptr);
- }
-
-#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
- unsigned int num_coords;
- const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
- if (num_coords)
- {
- FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
- if (ft_coords)
- {
- for (unsigned int i = 0; i < num_coords; i++)
- ft_coords[i] = coords[i] * 4;
- FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
- hb_free (ft_coords);
- }
- }
-#endif
+ _hb_ft_hb_font_changed (font, ft_face);
ft_face->generic.data = blob;
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
diff --git a/thirdparty/harfbuzz/src/hb-ft.h b/thirdparty/harfbuzz/src/hb-ft.h
index bf07115ab9..6a8a7abe8c 100644
--- a/thirdparty/harfbuzz/src/hb-ft.h
+++ b/thirdparty/harfbuzz/src/hb-ft.h
@@ -122,10 +122,17 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
HB_EXTERN int
hb_ft_font_get_load_flags (hb_font_t *font);
-/* Call when size or variations settings on underlying FT_Face change. */
+/* Call when size or variations settings on underlying FT_Face changed,
+ * and you want to update the hb_font_t from it. */
HB_EXTERN void
hb_ft_font_changed (hb_font_t *font);
+/* Call when size or variations settings on underlying hb_font_t may have
+ * changed, and you want to update the FT_Face from it. This call is fast
+ * if nothing changed on hb_font_t. Returns true if changed. */
+HB_EXTERN hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font);
+
/* Makes an hb_font_t use FreeType internally to implement font functions.
* Note: this internally creates an FT_Face. Use it when you create your
* hb_face_t using hb_face_create(). */
diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh
index 43a3098f65..d4461f166c 100644
--- a/thirdparty/harfbuzz/src/hb-iter.hh
+++ b/thirdparty/harfbuzz/src/hb-iter.hh
@@ -43,17 +43,12 @@
* is writable, then the iterator returns lvalues, otherwise it
* returns rvalues.
*
- * TODO Document more.
- *
- * If iterator implementation implements operator!=, then can be
+ * If iterator implementation implements operator!=, then it can be
* used in range-based for loop. That already happens if the iterator
* is random-access. Otherwise, the range-based for loop incurs
* one traversal to find end(), which can be avoided if written
* as a while-style for loop, or if iterator implements a faster
- * __end__() method.
- * TODO When opting in for C++17, address this by changing return
- * type of .end()?
- */
+ * __end__() method. */
/*
* Base classes for iterators.
@@ -75,10 +70,6 @@ struct hb_iter_t
iter_t* thiz () { return static_cast< iter_t *> (this); }
public:
- /* TODO:
- * Port operators below to use hb_enable_if to sniff which method implements
- * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
-
/* Operators. */
iter_t iter () const { return *thiz(); }
iter_t operator + () const { return *thiz(); }
@@ -87,8 +78,7 @@ struct hb_iter_t
explicit operator bool () const { return thiz()->__more__ (); }
unsigned len () const { return thiz()->__len__ (); }
/* The following can only be enabled if item_t is reference type. Otherwise
- * it will be returning pointer to temporary rvalue.
- * TODO Use a wrapper return type to fix for non-reference type. */
+ * it will be returning pointer to temporary rvalue. */
template <typename T = item_t,
hb_enable_if (std::is_reference<T>::value)>
hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh
index e52a6a4124..ff2a99f5ed 100644
--- a/thirdparty/harfbuzz/src/hb-machinery.hh
+++ b/thirdparty/harfbuzz/src/hb-machinery.hh
@@ -176,7 +176,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
void init () { instance.set_relaxed (nullptr); }
- void fini () { do_destroy (instance.get ()); }
+ void fini () { do_destroy (instance.get ()); init (); }
void free_instance ()
{
diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc
index 6c83c670c9..089615c72a 100644
--- a/thirdparty/harfbuzz/src/hb-map.cc
+++ b/thirdparty/harfbuzz/src/hb-map.cc
@@ -40,7 +40,7 @@
/**
- * hb_map_create: (Xconstructor)
+ * hb_map_create:
*
* Creates a new, initially empty map.
*
@@ -172,6 +172,25 @@ hb_map_allocation_successful (const hb_map_t *map)
return map->successful;
}
+/**
+ * hb_map_copy:
+ * @map: A map
+ *
+ * Allocate a copy of @map.
+ *
+ * Return value: Newly-allocated map.
+ *
+ * Since: 4.4.0
+ **/
+hb_map_t *
+hb_map_copy (const hb_map_t *map)
+{
+ hb_map_t *copy = hb_map_create ();
+ if (unlikely (!copy)) return nullptr;
+ copy->resize (map->population);
+ hb_copy (*map, *copy);
+ return copy;
+}
/**
* hb_map_set:
@@ -309,3 +328,20 @@ hb_map_is_equal (const hb_map_t *map,
return map->is_equal (*other);
}
+/**
+ * hb_map_hash:
+ * @map: A map
+ *
+ * Creates a hash representing @map.
+ *
+ * Return value:
+ * A hash of @map.
+ *
+ * Since: 4.4.0
+ **/
+HB_EXTERN unsigned int
+hb_map_hash (const hb_map_t *map)
+{
+ return map->hash ();
+}
+
diff --git a/thirdparty/harfbuzz/src/hb-map.h b/thirdparty/harfbuzz/src/hb-map.h
index 3f67c50b92..41d877d6a1 100644
--- a/thirdparty/harfbuzz/src/hb-map.h
+++ b/thirdparty/harfbuzz/src/hb-map.h
@@ -82,6 +82,9 @@ hb_map_get_user_data (hb_map_t *map,
HB_EXTERN hb_bool_t
hb_map_allocation_successful (const hb_map_t *map);
+HB_EXTERN hb_map_t *
+hb_map_copy (const hb_map_t *map);
+
HB_EXTERN void
hb_map_clear (hb_map_t *map);
@@ -95,6 +98,9 @@ HB_EXTERN hb_bool_t
hb_map_is_equal (const hb_map_t *map,
const hb_map_t *other);
+HB_EXTERN unsigned int
+hb_map_hash (const hb_map_t *map);
+
HB_EXTERN void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh
index aec7d87f42..5efad8d20c 100644
--- a/thirdparty/harfbuzz/src/hb-map.hh
+++ b/thirdparty/harfbuzz/src/hb-map.hh
@@ -34,15 +34,13 @@
* hb_hashmap_t
*/
+extern HB_INTERNAL const hb_codepoint_t minus_1;
+
template <typename K, typename V,
- typename k_invalid_t = K,
- typename v_invalid_t = V,
- k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
- v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
+ bool minus_one = false>
struct hb_hashmap_t
{
hb_hashmap_t () { init (); }
- hb_hashmap_t (std::nullptr_t) : hb_hashmap_t () {}
~hb_hashmap_t () { fini (); }
hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
@@ -68,38 +66,44 @@ struct hb_hashmap_t
struct item_t
{
K key;
+ uint32_t hash : 30;
+ uint32_t is_used_ : 1;
+ uint32_t is_tombstone_ : 1;
V value;
- uint32_t hash;
+
+ bool is_used () const { return is_used_; }
+ void set_used (bool is_used) { is_used_ = is_used; }
+ bool is_tombstone () const { return is_tombstone_; }
+ void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
+ bool is_real () const { return is_used_ && !is_tombstone_; }
+
+ template <bool v = minus_one,
+ hb_enable_if (v == false)>
+ static inline const V& default_value () { return Null(V); };
+ template <bool v = minus_one,
+ hb_enable_if (v == true)>
+ static inline const V& default_value ()
+ {
+ static_assert (hb_is_same (V, hb_codepoint_t), "");
+ return minus_1;
+ };
void clear ()
{
new (std::addressof (key)) K ();
- key = hb_coerce<K> (kINVALID);
new (std::addressof (value)) V ();
- value = hb_coerce<V> (vINVALID);
hash = 0;
+ is_used_ = false;
+ is_tombstone_ = false;
}
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; }
- bool is_unused () const
- {
- const K inv = hb_coerce<K> (kINVALID);
- return key == inv;
- }
- bool is_tombstone () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value == vinv;
- }
- bool is_real () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value != vinv;
- }
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
+ hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
+
+ uint32_t total_hash () const
+ { return (hash * 31) + hb_hash (value); }
};
hb_object_header_t header;
@@ -200,27 +204,39 @@ struct hb_hashmap_t
return true;
}
- bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
- bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
+ template <typename VV>
+ bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
- V get (K key) const
+ const V& get (K key) const
{
- if (unlikely (!items)) return hb_coerce<V> (vINVALID);
+ if (unlikely (!items)) return item_t::default_value ();
unsigned int i = bucket_for (key);
- return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
+ return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value ();
}
- void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
+ void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
/* Has interface. */
- typedef V value_t;
+ typedef const V& value_t;
value_t operator [] (K k) const { return get (k); }
- bool has (K k, V *vp = nullptr) const
+ bool has (K key, const V **vp = nullptr) const
{
- V v = (*this)[k];
- if (vp) *vp = v;
- const V vinv = hb_coerce<V> (vINVALID);
- return v != vinv;
+ if (unlikely (!items))
+ {
+ if (vp) *vp = &item_t::default_value ();
+ return false;
+ }
+ unsigned int i = bucket_for (key);
+ if (items[i].is_real () && items[i] == key)
+ {
+ if (vp) *vp = &items[i].value;
+ return true;
+ }
+ else
+ {
+ if (vp) *vp = &item_t::default_value ();
+ return false;
+ }
}
/* Projection. */
V operator () (K k) const { return get (k); }
@@ -242,8 +258,9 @@ struct hb_hashmap_t
uint32_t hash () const
{
uint32_t h = 0;
- for (auto pair : iter ())
- h ^= (hb_hash (pair.first) * 31) + hb_hash (pair.second);
+ for (const auto &item : + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real))
+ h ^= item.total_hash ();
return h;
}
@@ -271,6 +288,12 @@ struct hb_hashmap_t
| hb_filter (&item_t::is_real)
| hb_map (&item_t::get_pair)
)
+ auto iter_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::get_pair_ref)
+ )
auto keys () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
@@ -293,19 +316,16 @@ struct hb_hashmap_t
protected:
template <typename VV>
- bool set_with_hash (K key, uint32_t hash, VV&& value)
+ bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
{
if (unlikely (!successful)) return false;
- const K kinv = hb_coerce<K> (kINVALID);
- if (unlikely (key == kinv)) return true;
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash);
- const V vinv = hb_coerce<V> (vINVALID);
- if (value == vinv && items[i].key != key)
+ if (is_delete && items[i].key != key)
return true; /* Trying to delete non-existent key. */
- if (!items[i].is_unused ())
+ if (items[i].is_used ())
{
occupancy--;
if (!items[i].is_tombstone ())
@@ -313,27 +333,30 @@ struct hb_hashmap_t
}
items[i].key = key;
- items[i].value = value;
+ items[i].value = std::forward<VV> (value);
items[i].hash = hash;
+ items[i].set_used (true);
+ items[i].set_tombstone (is_delete);
occupancy++;
- if (!items[i].is_tombstone ())
+ if (!is_delete)
population++;
return true;
}
- unsigned int bucket_for (K key) const
+ unsigned int bucket_for (const K &key) const
{
return bucket_for_hash (key, hb_hash (key));
}
- unsigned int bucket_for_hash (K key, uint32_t hash) const
+ unsigned int bucket_for_hash (const K &key, uint32_t hash) const
{
+ hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
unsigned int i = hash % prime;
unsigned int step = 0;
unsigned int tombstone = (unsigned) -1;
- while (!items[i].is_unused ())
+ while (items[i].is_used ())
{
if (items[i].hash == hash && items[i] == key)
return i;
@@ -402,21 +425,14 @@ struct hb_hashmap_t
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>
+ true>
{
using hashmap = hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>;
+ true>;
~hb_map_t () = default;
hb_map_t () : hashmap () {}
- hb_map_t (std::nullptr_t) : hb_map_t () {}
hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;
diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh
index 90757d38ac..e97d790fc3 100644
--- a/thirdparty/harfbuzz/src/hb-meta.hh
+++ b/thirdparty/harfbuzz/src/hb-meta.hh
@@ -188,7 +188,7 @@ template <> struct hb_int_max<signed long long> : hb_integral_constant<signed l
template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigned long long, ULLONG_MAX> {};
#define hb_int_max(T) hb_int_max<T>::value
-#if __GNUG__ && __GNUC__ < 5
+#if defined(__GNUC__) && __GNUC__ < 5
#define hb_is_trivially_copyable(T) __has_trivial_copy(T)
#define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T)
#define hb_is_trivially_constructible(T) __has_trivial_constructor(T)
diff --git a/thirdparty/harfbuzz/src/hb-null.hh b/thirdparty/harfbuzz/src/hb-null.hh
index db38a4dfd2..78eb6474d5 100644
--- a/thirdparty/harfbuzz/src/hb-null.hh
+++ b/thirdparty/harfbuzz/src/hb-null.hh
@@ -37,7 +37,7 @@
/* Global nul-content Null pool. Enlarge as necessary. */
-#define HB_NULL_POOL_SIZE 384
+#define HB_NULL_POOL_SIZE 448
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
* of sizeof(T) and T::null_size, otherwise return sizeof(T).
@@ -108,7 +108,7 @@ struct NullHelper
/* Specializations for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
- extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)]; \
template <> \
struct Null<Namespace::Type> { \
static Namespace::Type const & get_null () { \
@@ -118,7 +118,7 @@ struct NullHelper
namespace Namespace { \
static_assert (true, "") /* Require semicolon after. */
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
- const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+ const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)]
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
index b5047002ac..4aa337f78b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
@@ -406,6 +406,8 @@ struct Charset1_2 {
void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
{
hb_codepoint_t gid = 1;
+ if (gid >= num_glyphs)
+ return;
for (unsigned i = 0;; i++)
{
hb_codepoint_t sid = ranges[i].first;
@@ -1138,7 +1140,8 @@ struct cff1
cff1_top_dict_interp_env_t env (fontDictStr);
cff1_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
- if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
+ if (unlikely (fontDicts.in_error ())) { fini (); return; }
+
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
PRIVDICTVAL *priv = &privateDicts[i];
@@ -1333,7 +1336,7 @@ struct cff1
if (names)
{
names->fini ();
- free (names);
+ hb_free (names);
}
SUPER::fini ();
@@ -1379,7 +1382,7 @@ struct cff1
hb_sorted_vector_t<gname_t> *names = glyph_names.get ();
if (unlikely (!names))
{
- names = (hb_sorted_vector_t<gname_t> *) calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
+ names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
if (likely (names))
{
names->init ();
@@ -1409,14 +1412,14 @@ struct cff1
if (names)
{
names->fini ();
- free (names);
+ hb_free (names);
}
goto retry;
}
- }
+ }
gname_t key = { hb_bytes_t (name, len), 0 };
- const gname_t *gname = glyph_names->bsearch (key);
+ const gname_t *gname = names ? names->bsearch (key) : nullptr;
if (!gname) return false;
hb_codepoint_t gid = sid_to_glyph (gname->sid);
if (!gid && gname->sid) return false;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
index 7e96d9c8b3..09c9fe93f3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
@@ -27,6 +27,8 @@
#ifndef HB_OT_CMAP_TABLE_HH
#define HB_OT_CMAP_TABLE_HH
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-shaper-arabic-pua.hh"
#include "hb-open-type.hh"
#include "hb-set.hh"
@@ -1476,33 +1478,47 @@ struct SubtableUnicodesCache {
private:
const void* base;
- hb_hashmap_t<intptr_t, hb_set_t*> cached_unicodes;
+ hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes;
public:
SubtableUnicodesCache(const void* cmap_base)
: base(cmap_base), cached_unicodes() {}
- ~SubtableUnicodesCache()
- {
- for (hb_set_t* s : cached_unicodes.values()) {
- hb_set_destroy (s);
- }
- }
- hb_set_t* set_for(const EncodingRecord* record)
+ hb_set_t* set_for (const EncodingRecord* record)
{
- if (!cached_unicodes.has ((intptr_t) record)) {
- hb_set_t* new_set = hb_set_create ();
- if (!cached_unicodes.set ((intptr_t) record, new_set)) {
- hb_set_destroy (new_set);
+ if (!cached_unicodes.has ((intptr_t) record))
+ {
+ hb_set_t *s = hb_set_create ();
+ if (unlikely (s->in_error ()))
+ return hb_set_get_empty ();
+
+ (base+record->subtable).collect_unicodes (s);
+
+ if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr<hb_set_t> {s})))
return hb_set_get_empty ();
- }
- (base+record->subtable).collect_unicodes (cached_unicodes.get ((intptr_t) record));
+
+ return s;
}
return cached_unicodes.get ((intptr_t) record);
}
};
+static inline uint_fast16_t
+_hb_symbol_pua_map (unsigned codepoint)
+{
+ if (codepoint <= 0x00FFu)
+ {
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ return 0xF000u + codepoint;
+ }
+ return 0;
+}
+
struct cmap
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
@@ -1726,7 +1742,24 @@ struct cmap
this->get_glyph_data = subtable;
if (unlikely (symbol))
- this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
+ {
+ switch ((unsigned) face->table.OS2->get_font_page ()) {
+ case OS2::font_page_t::FONT_PAGE_NONE:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_symbol_pua_map>;
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_simp_map>;
+ break;
+ case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_trad_map>;
+ break;
+#endif
+ default:
+ this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
+ break;
+ }
+ }
else
{
switch (subtable->u.format) {
@@ -1808,6 +1841,7 @@ struct cmap
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
+ typedef uint_fast16_t (*hb_pua_remap_func_t) (unsigned);
template <typename Type>
HB_INTERNAL static bool get_glyph_from (const void *obj,
@@ -1818,7 +1852,7 @@ struct cmap
return typed_obj->get_glyph (codepoint, glyph);
}
- template <typename Type>
+ template <typename Type, hb_pua_remap_func_t remap>
HB_INTERNAL static bool get_glyph_from_symbol (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph)
@@ -1827,15 +1861,8 @@ struct cmap
if (likely (typed_obj->get_glyph (codepoint, glyph)))
return true;
- if (codepoint <= 0x00FFu)
- {
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- return typed_obj->get_glyph (0xF000u + codepoint, glyph);
- }
+ if (hb_codepoint_t c = remap (codepoint))
+ return typed_obj->get_glyph (c, glyph);
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
index 24476eda17..bcab77f79d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
@@ -97,9 +97,10 @@ struct CPALV1Tail
c->push ();
for (const auto _ : colorLabels)
{
- if (!color_index_map->has (_)) continue;
+ const hb_codepoint_t *v;
+ if (!color_index_map->has (_, &v)) continue;
NameID new_color_idx;
- new_color_idx = color_index_map->get (_);
+ new_color_idx = *v;
if (!c->copy<NameID> (new_color_idx))
{
c->pop_discard ();
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
index 9741ebd450..d0e2235fb2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
@@ -298,6 +298,12 @@ struct sbix
const PNGHeader &png = *blob->as<PNGHeader>();
+ if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
+ {
+ hb_blob_destroy (blob);
+ return false;
+ }
+
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 0f44ee4d5f..af1bc86d48 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-font.cc
@@ -30,6 +30,7 @@
#include "hb-ot.h"
+#include "hb-cache.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-ot-face.hh"
@@ -58,6 +59,41 @@
* never need to call these functions directly.
**/
+struct hb_ot_font_t
+{
+ const hb_ot_face_t *ot_face;
+
+ /* h_advance caching */
+ mutable hb_atomic_int_t cached_coords_serial;
+ mutable hb_atomic_ptr_t<hb_advance_cache_t> advance_cache;
+};
+
+static hb_ot_font_t *
+_hb_ot_font_create (hb_font_t *font)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
+ if (unlikely (!ot_font))
+ return nullptr;
+
+ ot_font->ot_face = &font->face->table;
+
+ return ot_font;
+}
+
+static void
+_hb_ot_font_destroy (void *font_data)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
+
+ auto *cache = ot_font->advance_cache.get_relaxed ();
+ if (cache)
+ {
+ cache->fini ();
+ hb_free (cache);
+ }
+
+ hb_free (ot_font);
+}
static hb_bool_t
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
@@ -66,7 +102,8 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyph (unicode, glyph);
}
@@ -80,7 +117,8 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyphs (count,
first_unicode, unicode_stride,
first_glyph, glyph_stride);
@@ -94,7 +132,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
}
@@ -107,15 +146,83 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
- for (unsigned int i = 0; i < count; i++)
+#ifndef HB_NO_VAR
+ const OT::HVARVVAR &HVAR = *hmtx.var_table;
+ const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
+
+ bool use_cache = font->num_coords;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+ bool use_cache = false;
+#endif
+
+ hb_advance_cache_t *cache = nullptr;
+ if (use_cache)
{
- *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ retry:
+ cache = ot_font->advance_cache.get ();
+ if (unlikely (!cache))
+ {
+ cache = (hb_advance_cache_t *) hb_malloc (sizeof (hb_advance_cache_t));
+ if (unlikely (!cache))
+ {
+ use_cache = false;
+ goto out;
+ }
+
+ cache->init ();
+ if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
+ {
+ hb_free (cache);
+ goto retry;
+ }
+ ot_font->cached_coords_serial.set (font->serial_coords);
+ }
+ }
+ out:
+
+ if (!use_cache)
+ {
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font, varStore_cache));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
}
+ else
+ { /* Use cache. */
+ if (ot_font->cached_coords_serial.get () != (int) font->serial_coords)
+ {
+ ot_font->advance_cache->init ();
+ ot_font->cached_coords_serial.set (font->serial_coords);
+ }
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ hb_position_t v;
+ unsigned cv;
+ if (ot_font->advance_cache->get (*first_glyph, &cv))
+ v = cv;
+ else
+ {
+ v = hmtx.get_advance (*first_glyph, font, varStore_cache);
+ ot_font->advance_cache->set (*first_glyph, v);
+ }
+ *first_advance = font->em_scale_x (v);
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
}
#ifndef HB_NO_VERTICAL
@@ -128,16 +235,31 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
if (vmtx.has_data ())
+ {
+#ifndef HB_NO_VAR
+ const OT::HVARVVAR &VVAR = *vmtx.var_table;
+ const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+#endif
+
for (unsigned int i = 0; i < count; i++)
{
- *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+ *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font, varStore_cache));
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
+ }
else
{
hb_font_extents_t font_extents;
@@ -163,7 +285,8 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_position_t *y,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
*x = font->get_glyph_h_advance (glyph) / 2;
@@ -208,7 +331,8 @@ hb_ot_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
@@ -234,7 +358,9 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
+
if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
@@ -248,7 +374,9 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
+
if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
@@ -364,10 +492,14 @@ _hb_ot_get_font_funcs ()
void
hb_ot_font_set_funcs (hb_font_t *font)
{
+ hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+ if (unlikely (!ot_font))
+ return;
+
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
- &font->face->table,
- nullptr);
+ ot_font,
+ _hb_ot_font_destroy);
}
#ifndef HB_NO_VAR
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 866bb7e04c..c32ff7636d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -30,1334 +30,6 @@
#ifndef HB_OT_GLYF_TABLE_HH
#define HB_OT_GLYF_TABLE_HH
-#include "hb-open-type.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-var-gvar-table.hh"
-#include "hb-draw.hh"
-
-namespace OT {
-
-
-/*
- * loca -- Index to Location
- * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
- */
-#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
-
-#ifndef HB_MAX_COMPOSITE_OPERATIONS
-#define HB_MAX_COMPOSITE_OPERATIONS 100000
-#endif
-
-
-struct loca
-{
- friend struct glyf;
-
- static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- return_trace (true);
- }
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Location data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-
-/*
- * glyf -- TrueType Glyph Data
- * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
- */
-#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-
-
-struct glyf
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- /* Runtime checks as eager sanitizing each glyph is costy */
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_source_of (Iterator, unsigned int))>
- static bool
- _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
- {
- unsigned num_offsets = padded_offsets.len () + 1;
- unsigned entry_size = use_short_loca ? 2 : 4;
- char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
-
- if (unlikely (!loca_prime_data)) return false;
-
- DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
- entry_size, num_offsets, entry_size * num_offsets);
-
- if (use_short_loca)
- _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
- else
- _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
-
- hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
- entry_size * num_offsets,
- HB_MEMORY_MODE_WRITABLE,
- loca_prime_data,
- hb_free);
-
- bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
- && _add_head_and_set_loca_version (plan, use_short_loca);
-
- hb_blob_destroy (loca_blob);
- return result;
- }
-
- template<typename IteratorIn, typename IteratorOut,
- hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
- hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
- static void
- _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
- {
- unsigned int offset = 0;
- dest << 0;
- + it
- | hb_map ([=, &offset] (unsigned int padded_size)
- {
- offset += padded_size;
- DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
- return offset >> right_shift;
- })
- | hb_sink (dest)
- ;
- }
-
- /* requires source of SubsetGlyph complains the identifier isn't declared */
- template <typename Iterator>
- bool serialize (hb_serialize_context_t *c,
- Iterator it,
- bool use_short_loca,
- const hb_subset_plan_t *plan)
- {
- TRACE_SERIALIZE (this);
- unsigned init_len = c->length ();
- for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
-
- /* As a special case when all glyph in the font are empty, add a zero byte
- * to the table, so that OTS doesn’t reject it, and to make the table work
- * on Windows as well.
- * See https://github.com/khaledhosny/ots/issues/52 */
- if (init_len == c->length ())
- {
- HBUINT8 empty_byte;
- empty_byte = 0;
- c->copy (empty_byte);
- }
- return_trace (true);
- }
-
- /* Byte region(s) per glyph to output
- unpadded, hints removed if so requested
- If we fail to process a glyph we produce an empty (0-length) glyph */
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- glyf *glyf_prime = c->serializer->start_embed <glyf> ();
- if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-
- hb_vector_t<SubsetGlyph> glyphs;
- _populate_subset_glyphs (c->plan, &glyphs);
-
- auto padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::padded_size)
- ;
-
- unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
- bool use_short_loca = max_offset < 0x1FFFF;
-
-
- glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
- if (!use_short_loca) {
- padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::length)
- ;
- }
-
-
- if (unlikely (c->serializer->in_error ())) return_trace (false);
- return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
- padded_offsets,
- use_short_loca)));
- }
-
- template <typename SubsetGlyph>
- void
- _populate_subset_glyphs (const hb_subset_plan_t *plan,
- hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
- {
- OT::glyf::accelerator_t glyf (plan->source);
-
- + hb_range (plan->num_output_glyphs ())
- | hb_map ([&] (hb_codepoint_t new_gid)
- {
- SubsetGlyph subset_glyph = {0};
- subset_glyph.new_gid = new_gid;
-
- /* should never fail: all old gids should be mapped */
- if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
- return subset_glyph;
-
- if (new_gid == 0 &&
- !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
- subset_glyph.source_glyph = Glyph ();
- else
- subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- subset_glyph.drop_hints_bytes ();
- else
- subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
- return subset_glyph;
- })
- | hb_sink (glyphs)
- ;
- }
-
- static bool
- _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
- {
- hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
- hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
- hb_blob_destroy (head_blob);
-
- if (unlikely (!head_prime_blob))
- return false;
-
- head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
- head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
- bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
-
- hb_blob_destroy (head_prime_blob);
- return success;
- }
-
- struct CompositeGlyphChain
- {
- protected:
- enum composite_glyph_flag_t
- {
- ARG_1_AND_2_ARE_WORDS = 0x0001,
- ARGS_ARE_XY_VALUES = 0x0002,
- ROUND_XY_TO_GRID = 0x0004,
- WE_HAVE_A_SCALE = 0x0008,
- MORE_COMPONENTS = 0x0020,
- WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
- WE_HAVE_A_TWO_BY_TWO = 0x0080,
- WE_HAVE_INSTRUCTIONS = 0x0100,
- USE_MY_METRICS = 0x0200,
- OVERLAP_COMPOUND = 0x0400,
- SCALED_COMPONENT_OFFSET = 0x0800,
- UNSCALED_COMPONENT_OFFSET = 0x1000
- };
-
- public:
- unsigned int get_size () const
- {
- unsigned int size = min_size;
- /* arg1 and 2 are int16 */
- if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
- /* arg1 and 2 are int8 */
- else size += 2;
-
- /* One x 16 bit (scale) */
- if (flags & WE_HAVE_A_SCALE) size += 2;
- /* Two x 16 bit (xscale, yscale) */
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
- /* Four x 16 bit (xscale, scale01, scale10, yscale) */
- else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
-
- return size;
- }
-
- void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; }
- hb_codepoint_t get_glyph_index () const { return glyphIndex; }
-
- void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
- void set_overlaps_flag ()
- {
- flags = (uint16_t) flags | OVERLAP_COMPOUND;
- }
-
- bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
-
- bool has_more () const { return flags & MORE_COMPONENTS; }
- bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
- bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
- void get_anchor_points (unsigned int &point1, unsigned int &point2) const
- {
- const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- point1 = ((const HBUINT16 *) p)[0];
- point2 = ((const HBUINT16 *) p)[1];
- }
- else
- {
- point1 = p[0];
- point2 = p[1];
- }
- }
-
- void transform_points (contour_point_vector_t &points) const
- {
- float matrix[4];
- contour_point_t trans;
- if (get_transformation (matrix, trans))
- {
- if (scaled_offsets ())
- {
- points.translate (trans);
- points.transform (matrix);
- }
- else
- {
- points.transform (matrix);
- points.translate (trans);
- }
- }
- }
-
- protected:
- bool scaled_offsets () const
- { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
-
- bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
- {
- matrix[0] = matrix[3] = 1.f;
- matrix[1] = matrix[2] = 0.f;
-
- int tx, ty;
- const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- tx = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- ty = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- else
- {
- tx = *p++;
- ty = *p++;
- }
- if (is_anchored ()) tx = ty = 0;
-
- trans.init ((float) tx, (float) ty);
-
- {
- const F2DOT14 *points = (const F2DOT14 *) p;
- if (flags & WE_HAVE_A_SCALE)
- {
- matrix[0] = matrix[3] = points[0].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
- {
- matrix[0] = points[0].to_float ();
- matrix[3] = points[1].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_A_TWO_BY_TWO)
- {
- matrix[0] = points[0].to_float ();
- matrix[1] = points[1].to_float ();
- matrix[2] = points[2].to_float ();
- matrix[3] = points[3].to_float ();
- return true;
- }
- }
- return tx || ty;
- }
-
- protected:
- HBUINT16 flags;
- HBGlyphID16 glyphIndex;
- public:
- DEFINE_SIZE_MIN (4);
- };
-
- struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
- {
- typedef const CompositeGlyphChain *__item_t__;
- composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
- glyph (glyph_), current (nullptr), current_size (0)
- {
- set_next (current_);
- }
-
- composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
-
- const CompositeGlyphChain &__item__ () const { return *current; }
- bool __more__ () const { return current; }
- void __next__ ()
- {
- if (!current->has_more ()) { current = nullptr; return; }
-
- set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
- }
- bool operator != (const composite_iter_t& o) const
- { return glyph != o.glyph || current != o.current; }
-
-
- void set_next (const CompositeGlyphChain *composite)
- {
- if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
- unsigned size = composite->get_size ();
- if (!glyph.check_range (composite, size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
-
- current = composite;
- current_size = size;
- }
-
- private:
- hb_bytes_t glyph;
- __item_t__ current;
- unsigned current_size;
- };
-
- enum phantom_point_index_t
- {
- PHANTOM_LEFT = 0,
- PHANTOM_RIGHT = 1,
- PHANTOM_TOP = 2,
- PHANTOM_BOTTOM = 3,
- PHANTOM_COUNT = 4
- };
-
- struct accelerator_t;
-
- struct Glyph
- {
- enum simple_glyph_flag_t
- {
- FLAG_ON_CURVE = 0x01,
- FLAG_X_SHORT = 0x02,
- FLAG_Y_SHORT = 0x04,
- FLAG_REPEAT = 0x08,
- FLAG_X_SAME = 0x10,
- FLAG_Y_SAME = 0x20,
- FLAG_OVERLAP_SIMPLE = 0x40,
- FLAG_RESERVED2 = 0x80
- };
-
- private:
- struct GlyphHeader
- {
- bool has_data () const { return numberOfContours; }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
- /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
- extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
- extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
- extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
- extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
-
- return true;
- }
-
- HBINT16 numberOfContours;
- /* If the number of contours is
- * greater than or equal to zero,
- * this is a simple glyph; if negative,
- * this is a composite glyph. */
- FWORD xMin; /* Minimum x for coordinate data. */
- FWORD yMin; /* Minimum y for coordinate data. */
- FWORD xMax; /* Maximum x for coordinate data. */
- FWORD yMax; /* Maximum y for coordinate data. */
- public:
- DEFINE_SIZE_STATIC (10);
- };
-
- struct SimpleGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- unsigned int instruction_len_offset () const
- { return GlyphHeader::static_size + 2 * header.numberOfContours; }
-
- unsigned int length (unsigned int instruction_len) const
- { return instruction_len_offset () + 2 + instruction_len; }
-
- unsigned int instructions_length () const
- {
- unsigned int instruction_length_offset = instruction_len_offset ();
- if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
-
- const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
- /* Out of bounds of the current glyph */
- if (unlikely (length (instructionLength) > bytes.length)) return 0;
- return instructionLength;
- }
-
- const Glyph trim_padding () const
- {
- /* based on FontTools _g_l_y_f.py::trim */
- const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
- const uint8_t *glyph_end = glyph + bytes.length;
- /* simple glyph w/contours, possibly trimmable */
- glyph += instruction_len_offset ();
-
- if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
- unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
- unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
-
- glyph += 2 + num_instructions;
-
- unsigned int coord_bytes = 0;
- unsigned int coords_with_flags = 0;
- while (glyph < glyph_end)
- {
- uint8_t flag = *glyph;
- glyph++;
-
- unsigned int repeat = 1;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (glyph >= glyph_end)) return Glyph ();
- repeat = *glyph + 1;
- glyph++;
- }
-
- unsigned int xBytes, yBytes;
- xBytes = yBytes = 0;
- if (flag & FLAG_X_SHORT) xBytes = 1;
- else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
-
- if (flag & FLAG_Y_SHORT) yBytes = 1;
- else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
-
- coord_bytes += (xBytes + yBytes) * repeat;
- coords_with_flags += repeat;
- if (coords_with_flags >= num_coordinates) break;
- }
-
- if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
- return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
- }
-
- /* zero instruction length */
- void drop_hints ()
- {
- GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
- (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- unsigned int instructions_len = instructions_length ();
- unsigned int glyph_length = length (instructions_len);
- dest_start = bytes.sub_array (0, glyph_length - instructions_len);
- dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
- }
-
- void set_overlaps_flag ()
- {
- if (unlikely (!header.numberOfContours)) return;
-
- unsigned flags_offset = length (instructions_length ());
- if (unlikely (flags_offset + 1 > bytes.length)) return;
-
- HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
- first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
- }
-
- static bool read_points (const HBUINT8 *&p /* IN/OUT */,
- contour_point_vector_t &points_ /* IN/OUT */,
- const hb_bytes_t &bytes,
- void (* setter) (contour_point_t &_, float v),
- const simple_glyph_flag_t short_flag,
- const simple_glyph_flag_t same_flag)
- {
- float v = 0;
- for (unsigned i = 0; i < points_.length; i++)
- {
- uint8_t flag = points_[i].flag;
- if (flag & short_flag)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- if (flag & same_flag)
- v += *p++;
- else
- v -= *p++;
- }
- else
- {
- if (!(flag & same_flag))
- {
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
- v += *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- }
- setter (points_[i], v);
- }
- return true;
- }
-
- bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
- bool phantom_only = false) const
- {
- const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
- int num_contours = header.numberOfContours;
- if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
- unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
-
- points_.resize (num_points);
- for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
- if (phantom_only) return true;
-
- for (int i = 0; i < num_contours; i++)
- points_[endPtsOfContours[i]].is_end_point = true;
-
- /* Skip instructions */
- const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
- endPtsOfContours[num_contours]);
-
- /* Read flags */
- for (unsigned int i = 0; i < num_points; i++)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- uint8_t flag = *p++;
- points_[i].flag = flag;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- unsigned int repeat_count = *p++;
- while ((repeat_count-- > 0) && (++i < num_points))
- points_[i].flag = flag;
- }
- }
-
- /* Read x & y coordinates */
- return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; },
- FLAG_X_SHORT, FLAG_X_SAME)
- && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; },
- FLAG_Y_SHORT, FLAG_Y_SAME);
- }
- };
-
- struct CompositeGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- composite_iter_t get_iterator () const
- { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
-
- unsigned int instructions_length (hb_bytes_t bytes) const
- {
- unsigned int start = bytes.length;
- unsigned int end = bytes.length;
- const CompositeGlyphChain *last = nullptr;
- for (auto &item : get_iterator ())
- last = &item;
- if (unlikely (!last)) return 0;
-
- if (last->has_instructions ())
- start = (char *) last - &bytes + last->get_size ();
- if (unlikely (start > end)) return 0;
- return end - start;
- }
-
- /* Trimming for composites not implemented.
- * If removing hints it falls out of that. */
- const Glyph trim_padding () const { return Glyph (bytes); }
-
- void drop_hints ()
- {
- for (const auto &_ : get_iterator ())
- const_cast<CompositeGlyphChain &> (_).drop_instructions_flag ();
- }
-
- /* Chop instructions off the end */
- void drop_hints_bytes (hb_bytes_t &dest_start) const
- { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
-
- void set_overlaps_flag ()
- {
- const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
- .set_overlaps_flag ();
- }
- };
-
- enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
-
- public:
- composite_iter_t get_composite_iterator () const
- {
- if (type != COMPOSITE) return composite_iter_t ();
- return CompositeGlyph (*header, bytes).get_iterator ();
- }
-
- const Glyph trim_padding () const
- {
- switch (type) {
- case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
- case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
- default: return bytes;
- }
- }
-
- void drop_hints ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
- default: return;
- }
- }
-
- void set_overlaps_flag ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
- default: return;
- }
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
- default: return;
- }
- }
-
- /* Note: Recursively calls itself.
- * all_points includes phantom points
- */
- bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
- contour_point_vector_t &all_points /* OUT */,
- bool phantom_only = false,
- unsigned int depth = 0) const
- {
- if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
- contour_point_vector_t points;
-
- switch (type) {
- case COMPOSITE:
- {
- /* pseudo component points for each component in composite glyph */
- unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
- if (unlikely (!points.resize (num_points))) return false;
- for (unsigned i = 0; i < points.length; i++)
- points[i].init ();
- break;
- }
- case SIMPLE:
- if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
- return false;
- break;
- }
-
- /* Init phantom points */
- if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
- hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
- {
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
- int h_delta = (int) header->xMin -
- glyf_accelerator.hmtx->get_side_bearing (gid);
- int v_orig = (int) header->yMax +
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_side_bearing (gid)
-#else
- 0
-#endif
- ;
- unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
- unsigned v_adv =
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_advance (gid)
-#else
- - font->face->get_upem ()
-#endif
- ;
- phantoms[PHANTOM_LEFT].x = h_delta;
- phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
- phantoms[PHANTOM_TOP].y = v_orig;
- phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
- }
-
-#ifndef HB_NO_VAR
- glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
-#endif
-
- switch (type) {
- case SIMPLE:
- all_points.extend (points.as_array ());
- break;
- case COMPOSITE:
- {
- unsigned int comp_index = 0;
- for (auto &item : get_composite_iterator ())
- {
- contour_point_vector_t comp_points;
- if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ())
- .get_points (font, glyf_accelerator, comp_points,
- phantom_only, depth + 1)
- || comp_points.length < PHANTOM_COUNT))
- return false;
-
- /* Copy phantom points from component if USE_MY_METRICS flag set */
- if (item.is_use_my_metrics ())
- for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
- phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
-
- /* Apply component transformation & translation */
- item.transform_points (comp_points);
-
- /* Apply translation from gvar */
- comp_points.translate (points[comp_index]);
-
- if (item.is_anchored ())
- {
- unsigned int p1, p2;
- item.get_anchor_points (p1, p2);
- if (likely (p1 < all_points.length && p2 < comp_points.length))
- {
- contour_point_t delta;
- delta.init (all_points[p1].x - comp_points[p2].x,
- all_points[p1].y - comp_points[p2].y);
-
- comp_points.translate (delta);
- }
- }
-
- all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
-
- comp_index++;
- }
-
- all_points.extend (phantoms);
- } break;
- default:
- all_points.extend (phantoms);
- }
-
- if (depth == 0) /* Apply at top level */
- {
- /* Undocumented rasterizer behavior:
- * Shift points horizontally by the updated left side bearing
- */
- contour_point_t delta;
- delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
- if (delta.x) all_points.translate (delta);
- }
-
- return true;
- }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_glyph_extents_t *extents) const
- {
- if (type == EMPTY) return true; /* Empty glyph; zero extents. */
- return header->get_extents (font, glyf_accelerator, gid, extents);
- }
-
- hb_bytes_t get_bytes () const { return bytes; }
-
- Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
- hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
- header (bytes.as<GlyphHeader> ())
- {
- int num_contours = header->numberOfContours;
- if (unlikely (num_contours == 0)) type = EMPTY;
- else if (num_contours > 0) type = SIMPLE;
- else type = COMPOSITE; /* negative numbers */
- }
-
- protected:
- hb_bytes_t bytes;
- hb_codepoint_t gid;
- const GlyphHeader *header;
- unsigned type;
- };
-
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- {
- short_offset = false;
- num_glyphs = 0;
- loca_table = nullptr;
- glyf_table = nullptr;
-#ifndef HB_NO_VAR
- gvar = nullptr;
-#endif
- hmtx = nullptr;
-#ifndef HB_NO_VERTICAL
- vmtx = nullptr;
-#endif
- const OT::head &head = *face->table.head;
- if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
- /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
- return;
- short_offset = 0 == head.indexToLocFormat;
-
- loca_table = face->table.loca.get_blob (); // Needs no destruct!
- glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
-#ifndef HB_NO_VAR
- gvar = face->table.gvar;
-#endif
- hmtx = face->table.hmtx;
-#ifndef HB_NO_VERTICAL
- vmtx = face->table.vmtx;
-#endif
-
- num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
- num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
- }
- ~accelerator_t ()
- {
- glyf_table.destroy ();
- }
-
- bool has_data () const { return num_glyphs; }
-
- protected:
- template<typename T>
- bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
- {
- if (gid >= num_glyphs) return false;
-
- /* Making this allocfree is not that easy
- https://github.com/harfbuzz/harfbuzz/issues/2095
- mostly because of gvar handling in VF fonts,
- perhaps a separate path for non-VF fonts can be considered */
- contour_point_vector_t all_points;
-
- bool phantom_only = !consumer.is_consuming_contour_points ();
- if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
- return false;
-
- if (consumer.is_consuming_contour_points ())
- {
- for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
- consumer.consume_point (all_points[point_index]);
- consumer.points_end ();
- }
-
- /* Where to write phantoms, nullptr if not requested */
- contour_point_t *phantoms = consumer.get_phantoms_sink ();
- if (phantoms)
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
- phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
-
- return true;
- }
-
-#ifndef HB_NO_VAR
- struct points_aggregator_t
- {
- hb_font_t *font;
- hb_glyph_extents_t *extents;
- contour_point_t *phantoms;
-
- struct contour_bounds_t
- {
- contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
-
- void add (const contour_point_t &p)
- {
- min_x = hb_min (min_x, p.x);
- min_y = hb_min (min_y, p.y);
- max_x = hb_max (max_x, p.x);
- max_y = hb_max (max_y, p.y);
- }
-
- bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
-
- void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
- {
- if (unlikely (empty ()))
- {
- extents->width = 0;
- extents->x_bearing = 0;
- extents->height = 0;
- extents->y_bearing = 0;
- return;
- }
- extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
- extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
- }
-
- protected:
- float min_x, min_y, max_x, max_y;
- } bounds;
-
- points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
- {
- font = font_;
- extents = extents_;
- phantoms = phantoms_;
- if (extents) bounds = contour_bounds_t ();
- }
-
- void consume_point (const contour_point_t &point) { bounds.add (point); }
- void points_end () { bounds.get_extents (font, extents); }
-
- bool is_consuming_contour_points () { return extents; }
- contour_point_t *get_phantoms_sink () { return phantoms; }
- };
-
- public:
- unsigned
- get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- bool success = false;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (likely (font->num_coords == gvar->get_axis_count ()))
- success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
-
- if (unlikely (!success))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_advance (gid) :
-#endif
- hmtx->get_advance (gid);
-
- float result = is_vertical
- ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
- : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x;
- return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
- }
-
- int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- hb_glyph_extents_t extents;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_side_bearing (gid) :
-#endif
- hmtx->get_side_bearing (gid);
-
- return is_vertical
- ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
- : floorf (phantoms[PHANTOM_LEFT].x);
- }
-#endif
-
- public:
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- if (unlikely (gid >= num_glyphs)) return false;
-
-#ifndef HB_NO_VAR
- if (font->num_coords && font->num_coords == gvar->get_axis_count ())
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
-#endif
- return glyph_for_gid (gid).get_extents (font, *this, extents);
- }
-
- const Glyph
- glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
- {
- if (unlikely (gid >= num_glyphs)) return Glyph ();
-
- unsigned int start_offset, end_offset;
-
- if (short_offset)
- {
- const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
- start_offset = 2 * offsets[gid];
- end_offset = 2 * offsets[gid + 1];
- }
- else
- {
- const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
- start_offset = offsets[gid];
- end_offset = offsets[gid + 1];
- }
-
- if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
- return Glyph ();
-
- Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
- end_offset - start_offset), gid);
- return needs_padding_removal ? glyph.trim_padding () : glyph;
- }
-
- unsigned
- add_gid_and_children (hb_codepoint_t gid,
- hb_set_t *gids_to_retain,
- unsigned depth = 0,
- unsigned operation_count = 0) const
- {
- if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
- if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
- /* Check if is already visited */
- if (gids_to_retain->has (gid)) return operation_count;
-
- gids_to_retain->add (gid);
-
- auto it = glyph_for_gid (gid).get_composite_iterator ();
- while (it)
- {
- auto item = *(it++);
- operation_count =
- add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
- }
-
- return operation_count;
- }
-
- struct path_builder_t
- {
- hb_font_t *font;
- hb_draw_session_t *draw_session;
-
- struct optional_point_t
- {
- optional_point_t () { has_data = false; }
- optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
-
- bool has_data;
- float x;
- float y;
-
- optional_point_t lerp (optional_point_t p, float t)
- { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
- } first_oncurve, first_offcurve, last_offcurve;
-
- path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
- {
- font = font_;
- draw_session = &draw_session_;
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- }
-
- /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
- See also:
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
- * https://stackoverflow.com/a/20772557 */
- void consume_point (const contour_point_t &point)
- {
- bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
- optional_point_t p (point.x, point.y);
- if (!first_oncurve.has_data)
- {
- if (is_on_curve)
- {
- first_oncurve = p;
- draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- }
- else
- {
- if (first_offcurve.has_data)
- {
- optional_point_t mid = first_offcurve.lerp (p, .5f);
- first_oncurve = mid;
- last_offcurve = p;
- draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- }
- else
- first_offcurve = p;
- }
- }
- else
- {
- if (last_offcurve.has_data)
- {
- if (is_on_curve)
- {
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- last_offcurve = optional_point_t ();
- }
- else
- {
- optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- last_offcurve = p;
- }
- }
- else
- {
- if (is_on_curve)
- draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
- else
- last_offcurve = p;
- }
- }
-
- if (point.is_end_point)
- {
- if (first_offcurve.has_data && last_offcurve.has_data)
- {
- optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
- last_offcurve = optional_point_t ();
- /* now check the rest */
- }
-
- if (first_offcurve.has_data && first_oncurve.has_data)
- draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
- font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (last_offcurve.has_data && first_oncurve.has_data)
- draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
- font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (first_oncurve.has_data)
- draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
- else if (first_offcurve.has_data)
- {
- float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
- draw_session->move_to (x, y);
- draw_session->quadratic_to (x, y, x, y);
- }
-
- /* Getting ready for the next contour */
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- draw_session->close_path ();
- }
- }
- void points_end () {}
-
- bool is_consuming_contour_points () { return true; }
- contour_point_t *get_phantoms_sink () { return nullptr; }
- };
-
- bool
- get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
- { return get_points (font, gid, path_builder_t (font, draw_session)); }
-
-#ifndef HB_NO_VAR
- const gvar_accelerator_t *gvar;
-#endif
- const hmtx_accelerator_t *hmtx;
-#ifndef HB_NO_VERTICAL
- const vmtx_accelerator_t *vmtx;
-#endif
-
- private:
- bool short_offset;
- unsigned int num_glyphs;
- hb_blob_ptr_t<loca> loca_table;
- hb_blob_ptr_t<glyf> glyf_table;
- };
-
- struct SubsetGlyph
- {
- hb_codepoint_t new_gid;
- hb_codepoint_t old_gid;
- Glyph source_glyph;
- hb_bytes_t dest_start; /* region of source_glyph to copy first */
- hb_bytes_t dest_end; /* region of source_glyph to copy second */
-
- bool serialize (hb_serialize_context_t *c,
- bool use_short_loca,
- const hb_subset_plan_t *plan) const
- {
- TRACE_SERIALIZE (this);
-
- hb_bytes_t dest_glyph = dest_start.copy (c);
- dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
- unsigned int pad_length = use_short_loca ? padding () : 0;
- DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
-
- HBUINT8 pad;
- pad = 0;
- while (pad_length > 0)
- {
- c->embed (pad);
- pad_length--;
- }
-
- if (unlikely (!dest_glyph.length)) return_trace (true);
-
- /* update components gids */
- for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
- {
- hb_codepoint_t new_gid;
- if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid))
- const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
- }
-
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- Glyph (dest_glyph).drop_hints ();
-
- if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
- Glyph (dest_glyph).set_overlaps_flag ();
-
- return_trace (true);
- }
-
- void drop_hints_bytes ()
- { source_glyph.drop_hints_bytes (dest_start, dest_end); }
-
- unsigned int length () const { return dest_start.length + dest_end.length; }
- /* pad to 2 to ensure 2-byte loca will be ok */
- unsigned int padding () const { return length () % 2; }
- unsigned int padded_size () const { return length () + padding (); }
- };
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Glyphs data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-struct glyf_accelerator_t : glyf::accelerator_t {
- glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {}
-};
-
-
-} /* namespace OT */
-
+#include "OT/glyf/glyf.hh"
#endif /* HB_OT_GLYF_TABLE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
index d5e1fc91d2..d0e46e0b0f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -242,7 +242,7 @@ struct hmtxvmtx
return side_bearing;
if (var_table.get_length ())
- return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+ return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords);
return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
@@ -284,7 +284,8 @@ struct hmtxvmtx
}
unsigned int get_advance (hb_codepoint_t glyph,
- hb_font_t *font) const
+ hb_font_t *font,
+ VariationStore::cache_t *store_cache = nullptr) const
{
unsigned int advance = get_advance (glyph);
@@ -293,7 +294,7 @@ struct hmtxvmtx
return advance;
if (var_table.get_length ())
- return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
+ return advance + roundf (var_table->get_advance_var (glyph, font, store_cache)); // TODO Optimize?!
return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
@@ -310,7 +311,7 @@ struct hmtxvmtx
unsigned int default_advance;
- private:
+ public:
hb_blob_ptr_t<hmtxvmtx> table;
hb_blob_ptr_t<HVARVVAR> var_table;
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index b644df708d..d343805346 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -102,7 +102,7 @@ static void ClassDef_remap_and_serialize (
struct hb_prune_langsys_context_t
{
hb_prune_langsys_context_t (const void *table_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
const hb_map_t *duplicate_feature_map_,
hb_set_t *new_collected_feature_indexes_)
:table (table_),
@@ -122,7 +122,7 @@ struct hb_prune_langsys_context_t
public:
const void *table;
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *duplicate_feature_map;
hb_set_t *new_feature_indexes;
@@ -162,14 +162,14 @@ struct hb_subset_layout_context_t :
hb_subset_context_t *subset_context;
const hb_tag_t table_tag;
const hb_map_t *lookup_index_map;
- const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *feature_index_map;
unsigned cur_script_index;
hb_subset_layout_context_t (hb_subset_context_t *c_,
hb_tag_t tag_,
hb_map_t *lookup_map_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
hb_map_t *feature_index_map_) :
subset_context (c_),
table_tag (tag_),
@@ -659,7 +659,8 @@ struct LangSys
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
- out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
+ const unsigned *v;
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
if (!l->visitFeatureIndex (featureIndex.len))
return_trace (false);
@@ -722,12 +723,8 @@ struct Script
if (!c->script_langsys_map->has (script_index))
{
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
- {
- hb_set_destroy (empty_set);
+ if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return;
- }
}
unsigned langsys_count = get_lang_sys_count ();
@@ -2004,6 +2001,8 @@ struct ClassDefFormat1
return_trace (c->check_struct (this) && classValue.sanitize (c));
}
+ unsigned cost () const { return 1; }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
@@ -2240,6 +2239,8 @@ struct ClassDefFormat2
return_trace (rangeRecord.sanitize (c));
}
+ unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
@@ -2480,6 +2481,15 @@ struct ClassDef
}
}
+ unsigned cost () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.cost ();
+ case 2: return u.format2.cost ();
+ default:return 0u;
+ }
+ }
+
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
@@ -2601,14 +2611,27 @@ struct VarRegionAxis
DEFINE_SIZE_STATIC (6);
};
+#define REGION_CACHE_ITEM_CACHE_INVALID 2.f
+
struct VarRegionList
{
+ using cache_t = float;
+
float evaluate (unsigned int region_index,
- const int *coords, unsigned int coord_len) const
+ const int *coords, unsigned int coord_len,
+ cache_t *cache = nullptr) const
{
if (unlikely (region_index >= regionCount))
return 0.;
+ float *cached_value = nullptr;
+ if (cache)
+ {
+ cached_value = &(cache[region_index]);
+ if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+ return *cached_value;
+ }
+
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
float v = 1.;
@@ -2618,9 +2641,16 @@ struct VarRegionList
int coord = i < coord_len ? coords[i] : 0;
float factor = axes[i].evaluate (coord);
if (factor == 0.f)
+ {
+ if (cache)
+ *cached_value = 0.;
return 0.;
+ }
v *= factor;
}
+
+ if (cache)
+ *cached_value = v;
return v;
}
@@ -2668,7 +2698,7 @@ struct VarData
{ return regionIndices.len; }
unsigned int get_row_size () const
- { return shortCount + regionIndices.len; }
+ { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
unsigned int get_size () const
{ return min_size
@@ -2678,13 +2708,17 @@ struct VarData
float get_delta (unsigned int inner,
const int *coords, unsigned int coord_count,
- const VarRegionList &regions) const
+ const VarRegionList &regions,
+ VarRegionList::cache_t *cache = nullptr) const
{
if (unlikely (inner >= itemCount))
return 0.;
unsigned int count = regionIndices.len;
- unsigned int scount = shortCount;
+ bool is_long = longWords ();
+ unsigned word_count = wordCount ();
+ unsigned int scount = is_long ? count - word_count : word_count;
+ unsigned int lcount = is_long ? word_count : 0;
const HBUINT8 *bytes = get_delta_bytes ();
const HBUINT8 *row = bytes + inner * (scount + count);
@@ -2692,16 +2726,22 @@ struct VarData
float delta = 0.;
unsigned int i = 0;
- const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+ const HBINT16 *lcursor = reinterpret_cast<const HBINT16 *> (row);
+ for (; i < lcount; i++)
+ {
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
+ delta += scalar * *lcursor++;
+ }
+ const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
for (; i < scount; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *scursor++;
}
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
for (; i < count; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *bcursor++;
}
@@ -2725,7 +2765,7 @@ struct VarData
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
regionIndices.sanitize (c) &&
- shortCount <= regionIndices.len &&
+ wordCount () <= regionIndices.len &&
c->check_range (get_delta_bytes (),
itemCount,
get_row_size ()));
@@ -2740,43 +2780,66 @@ struct VarData
if (unlikely (!c->extend_min (this))) return_trace (false);
itemCount = inner_map.get_next_value ();
- /* Optimize short count */
- unsigned short ri_count = src->regionIndices.len;
- enum delta_size_t { kZero=0, kByte, kShort };
+ /* Optimize word count */
+ unsigned ri_count = src->regionIndices.len;
+ enum delta_size_t { kZero=0, kNonWord, kWord };
hb_vector_t<delta_size_t> delta_sz;
hb_vector_t<unsigned int> ri_map; /* maps old index to new index */
delta_sz.resize (ri_count);
ri_map.resize (ri_count);
- unsigned int new_short_count = 0;
+ unsigned int new_word_count = 0;
unsigned int r;
+
+ bool has_long = false;
+ if (src->longWords ())
+ {
+ for (r = 0; r < ri_count; r++)
+ {
+ for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
+ {
+ unsigned int old = inner_map.backward (i);
+ int32_t delta = src->get_item_delta (old, r);
+ if (delta < -65536 || 65535 < delta)
+ {
+ has_long = true;
+ break;
+ }
+ }
+ }
+ }
+
+ signed min_threshold = has_long ? -65536 : -128;
+ signed max_threshold = has_long ? +65535 : +127;
for (r = 0; r < ri_count; r++)
{
delta_sz[r] = kZero;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{
unsigned int old = inner_map.backward (i);
- int16_t delta = src->get_item_delta (old, r);
- if (delta < -128 || 127 < delta)
+ int32_t delta = src->get_item_delta (old, r);
+ if (delta < min_threshold || max_threshold < delta)
{
- delta_sz[r] = kShort;
- new_short_count++;
+ delta_sz[r] = kWord;
+ new_word_count++;
break;
}
else if (delta != 0)
- delta_sz[r] = kByte;
+ delta_sz[r] = kNonWord;
}
}
- unsigned int short_index = 0;
- unsigned int byte_index = new_short_count;
+
+ unsigned int word_index = 0;
+ unsigned int non_word_index = new_word_count;
unsigned int new_ri_count = 0;
for (r = 0; r < ri_count; r++)
if (delta_sz[r])
{
- ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
+ ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
new_ri_count++;
}
- shortCount = new_short_count;
+ wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
+
regionIndices.len = new_ri_count;
if (unlikely (!c->extend (this))) return_trace (false);
@@ -2816,28 +2879,55 @@ struct VarData
HBUINT8 *get_delta_bytes ()
{ return &StructAfter<HBUINT8> (regionIndices); }
- int16_t get_item_delta (unsigned int item, unsigned int region) const
+ int32_t get_item_delta (unsigned int item, unsigned int region) const
{
if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
- const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- return ((const HBINT16 *)p)[region];
+ const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size ();
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ return ((const HBINT32 *) p)[region];
+ else
+ return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
+ }
else
- return (p + HBINT16::static_size * shortCount)[region - shortCount];
+ {
+ if (region < word_count)
+ return ((const HBINT16 *) p)[region];
+ else
+ return (p + HBINT16::static_size * word_count)[region - word_count];
+ }
}
- void set_item_delta (unsigned int item, unsigned int region, int16_t delta)
+ void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
{
HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- ((HBINT16 *)p)[region] = delta;
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ ((HBINT32 *) p)[region] = delta;
+ else
+ ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
+ }
else
- (p + HBINT16::static_size * shortCount)[region - shortCount] = delta;
+ {
+ if (region < word_count)
+ ((HBINT16 *) p)[region] = delta;
+ else
+ (p + HBINT16::static_size * word_count)[region - word_count] = delta;
+ }
}
+ bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
+ unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
+
protected:
HBUINT16 itemCount;
- HBUINT16 shortCount;
+ HBUINT16 wordSizeCount;
Array16Of<HBUINT16> regionIndices;
/*UnsizedArrayOf<HBUINT8>bytesX;*/
public:
@@ -2846,9 +2936,28 @@ struct VarData
struct VariationStore
{
+ using cache_t = VarRegionList::cache_t;
+
+ cache_t *create_cache () const
+ {
+ auto &r = this+regions;
+ unsigned count = r.regionCount;
+
+ float *cache = (float *) hb_malloc (sizeof (float) * count);
+ if (unlikely (!cache)) return nullptr;
+
+ for (unsigned i = 0; i < count; i++)
+ cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
+
+ return cache;
+ }
+
+ static void destroy_cache (cache_t *cache) { hb_free (cache); }
+
private:
float get_delta (unsigned int outer, unsigned int inner,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
#ifdef HB_NO_VAR
return 0.f;
@@ -2859,16 +2968,18 @@ struct VariationStore
return (this+dataSets[outer]).get_delta (inner,
coords, coord_count,
- this+regions);
+ this+regions,
+ cache);
}
public:
float get_delta (unsigned int index,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
unsigned int outer = index >> 16;
unsigned int inner = index & 0xFFFF;
- return get_delta (outer, inner, coords, coord_count);
+ return get_delta (outer, inner, coords, coord_count, cache);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2995,6 +3106,8 @@ struct VariationStore
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
};
+#undef REGION_CACHE_ITEM_CACHE_INVALID
+
/*
* Feature Variations
*/
@@ -3462,11 +3575,15 @@ struct VariationDevice
private:
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_x (get_delta (font, store)); }
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_x (get_delta (font, store, store_cache)); }
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_y (get_delta (font, store)); }
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_y (get_delta (font, store, store_cache)); }
VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
{
@@ -3500,9 +3617,11 @@ struct VariationDevice
private:
- float get_delta (hb_font_t *font, const VariationStore &store) const
+ float get_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- return store.get_delta (varIdx, font->coords, font->num_coords);
+ return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache);
}
protected:
@@ -3525,7 +3644,9 @@ struct DeviceHeader
struct Device
{
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3535,13 +3656,15 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_x_delta (font, store);
+ return u.variation.get_x_delta (font, store, store_cache);
#endif
default:
return 0;
}
}
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3551,7 +3674,7 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_y_delta (font, store);
+ return u.variation.get_y_delta (font, store, store_cache);
#endif
default:
return 0;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
index a76d644c4b..9d47bac2b9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -571,7 +571,7 @@ struct GDEF
static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
switch (klass) {
- default: return 0;
+ default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
case MarkGlyph:
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
index 2f9186a2a7..064d31cdff 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -29,3090 +29,14 @@
#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
#define HB_OT_LAYOUT_GPOS_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GPOS.hh"
namespace OT {
-struct MarkArray;
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */);
-
-/* buffer **position** var allocations */
-#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
-#define attach_type() var.u8[2] /* attachment type */
-/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
-
-enum attach_type_t {
- ATTACH_TYPE_NONE = 0X00,
-
- /* Each attachment should be either a mark or a cursive; can't be both. */
- ATTACH_TYPE_MARK = 0X01,
- ATTACH_TYPE_CURSIVE = 0X02,
-};
-
-
-/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
-
-typedef HBUINT16 Value;
-
-typedef UnsizedArrayOf<Value> ValueRecord;
-
-struct ValueFormat : HBUINT16
-{
- enum Flags {
- xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
- yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
- xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
- yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
- xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
- yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
- xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
- yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
- ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
- reserved = 0xF000u, /* For future use */
-
- devices = 0x00F0u /* Mask for having any Device table */
- };
-
-/* All fields are options. Only those available advance the value pointer. */
-#if 0
- HBINT16 xPlacement; /* Horizontal adjustment for
- * placement--in design units */
- HBINT16 yPlacement; /* Vertical adjustment for
- * placement--in design units */
- HBINT16 xAdvance; /* Horizontal adjustment for
- * advance--in design units (only used
- * for horizontal writing) */
- HBINT16 yAdvance; /* Vertical adjustment for advance--in
- * design units (only used for vertical
- * writing) */
- Offset16To<Device> xPlaDevice; /* Offset to Device table for
- * horizontal placement--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
- * placement--measured from beginning
- * of PosTable (may be NULL) */
- Offset16To<Device> xAdvDevice; /* Offset to Device table for
- * horizontal advance--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
- * advance--measured from beginning of
- * PosTable (may be NULL) */
-#endif
-
- IntType& operator = (uint16_t i) { v = i; return *this; }
-
- unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
- unsigned int get_size () const { return get_len () * Value::static_size; }
-
- bool apply_value (hb_ot_apply_context_t *c,
- const void *base,
- const Value *values,
- hb_glyph_position_t &glyph_pos) const
- {
- bool ret = false;
- unsigned int format = *this;
- if (!format) return ret;
-
- hb_font_t *font = c->font;
- bool horizontal =
-#ifndef HB_NO_VERTICAL
- HB_DIRECTION_IS_HORIZONTAL (c->direction)
-#else
- true
-#endif
- ;
-
- if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
- if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
- if (format & xAdvance) {
- if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
- values++;
- }
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (format & yAdvance) {
- if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
- values++;
- }
-
- if (!has_device ()) return ret;
-
- bool use_x_device = font->x_ppem || font->num_coords;
- bool use_y_device = font->y_ppem || font->num_coords;
-
- if (!use_x_device && !use_y_device) return ret;
-
- const VariationStore &store = c->var_store;
-
- /* pixel -> fractional pixel */
- if (format & xPlaDevice) {
- if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yPlaDevice) {
- if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- if (format & xAdvDevice) {
- if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yAdvDevice) {
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- return ret;
- }
-
- unsigned int get_effective_format (const Value *values) const
- {
- unsigned int format = *this;
- for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
- if (format & flag) should_drop (*values++, (Flags) flag, &format);
- }
-
- return format;
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned int get_effective_format (Iterator it) const {
- unsigned int new_format = 0;
-
- for (const hb_array_t<const Value>& values : it)
- new_format = new_format | get_effective_format (&values);
-
- return new_format;
- }
-
- void copy_values (hb_serialize_context_t *c,
- unsigned int new_format,
- const void *base,
- const Value *values,
- const hb_map_t *layout_variation_idx_map) const
- {
- unsigned int format = *this;
- if (!format) return;
-
- if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
- if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
- if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
- if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
-
- if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- }
-
- void copy_value (hb_serialize_context_t *c,
- unsigned int new_format,
- Flags flag,
- Value value) const
- {
- // Filter by new format.
- if (!(new_format & flag)) return;
- c->copy (value);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *base,
- const hb_array_t<const Value>& values) const
- {
- unsigned format = *this;
- unsigned i = 0;
- if (format & xPlacement) i++;
- if (format & yPlacement) i++;
- if (format & xAdvance) i++;
- if (format & yAdvance) i++;
- if (format & xPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::xAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
- }
-
- private:
- bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- unsigned int format = *this;
-
- if (format & xPlacement) values++;
- if (format & yPlacement) values++;
- if (format & xAdvance) values++;
- if (format & yAdvance) values++;
-
- if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-
- return true;
- }
-
- static inline Offset16To<Device>& get_device (Value* value)
- {
- return *static_cast<Offset16To<Device> *> (value);
- }
- static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *static_cast<const Offset16To<Device> *> (value);
- }
-
- bool copy_device (hb_serialize_context_t *c, const void *base,
- const Value *src_value, const hb_map_t *layout_variation_idx_map) const
- {
- Value *dst_value = c->copy (*src_value);
-
- if (!dst_value) return false;
- if (*dst_value == 0) return true;
-
- *dst_value = 0;
- c->push ();
- if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
- {
- c->add_link (*dst_value, c->pop_pack ());
- return true;
- }
- else
- {
- c->pop_discard ();
- return false;
- }
- }
-
- static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *reinterpret_cast<const HBINT16 *> (value);
- }
-
- public:
-
- bool has_device () const
- {
- unsigned int format = *this;
- return (format & devices) != 0;
- }
-
- bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
- }
-
- bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
- {
- TRACE_SANITIZE (this);
- unsigned int len = get_len ();
-
- if (!c->check_range (values, count, get_size ())) return_trace (false);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += len;
- }
-
- return_trace (true);
- }
-
- /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
- bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
- {
- TRACE_SANITIZE (this);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += stride;
- }
-
- return_trace (true);
- }
-
- private:
-
- void should_drop (Value value, Flags flag, unsigned int* format) const
- {
- if (value) return;
- *format = *format & ~flag;
- }
-
-};
-
-template<typename Iterator, typename SrcLookup>
-static void SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map);
-
-
-struct AnchorFormat1
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- AnchorFormat1* out = c->embed<AnchorFormat1> (this);
- if (!out) return_trace (out);
- out->format = 1;
- return_trace (out);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct AnchorFormat2
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
-
-#ifdef HB_NO_HINTING
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- return;
-#endif
-
- unsigned int x_ppem = font->x_ppem;
- unsigned int y_ppem = font->y_ppem;
- hb_position_t cx = 0, cy = 0;
- bool ret;
-
- ret = (x_ppem || y_ppem) &&
- font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
- *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
- *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat2* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed<AnchorFormat2> (this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- HBUINT16 anchorPoint; /* Index to glyph contour point */
- public:
- DEFINE_SIZE_STATIC (8);
-};
-
-struct AnchorFormat3
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
-
- if (font->x_ppem || font->num_coords)
- *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
- if (font->y_ppem || font->num_coords)
- *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
- }
-
- AnchorFormat3* copy (hb_serialize_context_t *c,
- const hb_map_t *layout_variation_idx_map) const
- {
- TRACE_SERIALIZE (this);
- if (!layout_variation_idx_map) return_trace (nullptr);
-
- auto *out = c->embed<AnchorFormat3> (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
- (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 3 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- Offset16To<Device>
- xDeviceTable; /* Offset to Device table for X
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- Offset16To<Device>
- yDeviceTable; /* Offset to Device table for Y
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- public:
- DEFINE_SIZE_STATIC (10);
-};
-
-struct Anchor
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- *x = *y = 0;
- switch (u.format) {
- case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
- default: return;
- }
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!u.format.sanitize (c)) return_trace (false);
- switch (u.format) {
- case 1: return_trace (u.format1.sanitize (c));
- case 2: return_trace (u.format2.sanitize (c));
- case 3: return_trace (u.format3.sanitize (c));
- default:return_trace (true);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- switch (u.format) {
- case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- case 2:
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- // AnchorFormat 2 just containins extra hinting information, so
- // if hints are being dropped convert to format 1.
- return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- }
- return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
- case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
- c->plan->layout_variation_idx_map))));
- default:return_trace (false);
- }
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- switch (u.format) {
- case 1: case 2:
- return;
- case 3:
- u.format3.collect_variation_indices (c);
- return;
- default: return;
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- AnchorFormat1 format1;
- AnchorFormat2 format2;
- AnchorFormat3 format3;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-
-struct AnchorMatrix
-{
- const Anchor& get_anchor (unsigned int row, unsigned int col,
- unsigned int cols, bool *found) const
- {
- *found = false;
- if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
- *found = !matrixZ[row * cols + col].is_null ();
- return this+matrixZ[row * cols + col];
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- Iterator index_iter) const
- {
- for (unsigned i : index_iter)
- (this+matrixZ[i]).collect_variation_indices (c);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- unsigned num_rows,
- Iterator index_iter) const
- {
- TRACE_SUBSET (this);
-
- auto *out = c->serializer->start_embed (this);
-
- if (!index_iter) return_trace (false);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- out->rows = num_rows;
- for (const unsigned i : index_iter)
- {
- auto *offset = c->serializer->embed (matrixZ[i]);
- if (!offset) return_trace (false);
- offset->serialize_subset (c, matrixZ[i], this);
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
- {
- TRACE_SANITIZE (this);
- if (!c->check_struct (this)) return_trace (false);
- if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
- unsigned int count = rows * cols;
- if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
- for (unsigned int i = 0; i < count; i++)
- if (!matrixZ[i].sanitize (c, this)) return_trace (false);
- return_trace (true);
- }
-
- HBUINT16 rows; /* Number of rows */
- UnsizedArrayOf<Offset16To<Anchor>>
- matrixZ; /* Matrix of offsets to Anchor tables--
- * from beginning of AnchorMatrix table */
- public:
- DEFINE_SIZE_ARRAY (2, matrixZ);
-};
-
-
-struct MarkRecord
-{
- friend struct MarkArray;
-
- unsigned get_class () const { return (unsigned) klass; }
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
- }
-
- MarkRecord *subset (hb_subset_context_t *c,
- const void *src_base,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->klass = klass_mapping->get (klass);
- out->markAnchor.serialize_subset (c, markAnchor, src_base);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+markAnchor).collect_variation_indices (c);
- }
-
- protected:
- HBUINT16 klass; /* Class defined for this mark */
- Offset16To<Anchor>
- markAnchor; /* Offset to Anchor table--from
- * beginning of MarkArray table */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
-{
- bool apply (hb_ot_apply_context_t *c,
- unsigned int mark_index, unsigned int glyph_index,
- const AnchorMatrix &anchors, unsigned int class_count,
- unsigned int glyph_pos) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
- unsigned int mark_class = record.klass;
-
- const Anchor& mark_anchor = this + record.markAnchor;
- bool found;
- const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
- /* If this subtable doesn't have an anchor for this base and this class,
- * return false such that the subsequent subtables have a chance at it. */
- if (unlikely (!found)) return_trace (false);
-
- float mark_x, mark_y, base_x, base_y;
-
- buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
- mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
-
- hb_glyph_position_t &o = buffer->cur_pos();
- o.x_offset = roundf (base_x - mark_x);
- o.y_offset = roundf (base_y - mark_y);
- o.attach_type() = ATTACH_TYPE_MARK;
- o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto* out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- auto mark_iter =
- + hb_zip (coverage, this->iter ())
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- ;
-
- unsigned new_length = 0;
- for (const auto& mark_record : mark_iter) {
- if (unlikely (!mark_record.subset (c, this, klass_mapping)))
- return_trace (false);
- new_length++;
- }
-
- if (unlikely (!c->serializer->check_assign (out->len, new_length,
- HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
- return_trace (false);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (Array16Of<MarkRecord>::sanitize (c, this));
- }
-};
-
-
-/* Lookups */
-
-struct SinglePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (c->glyph_set)
- ;
-
- if (!it) return;
- valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- valueFormat.apply_value (c, this, values, buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (this))) return;
- if (unlikely (!c->check_assign (valueFormat,
- newFormat,
- HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
-
- for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
- {
- src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
- // Only serialize the first entry in the iterator, the rest are assumed to
- // be the same.
- break;
- }
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_value (c, this, values));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- ValueRecord values; /* Defines positioning
- * value(s)--applied to all glyphs in
- * the Coverage table */
- public:
- DEFINE_SIZE_ARRAY (6, values);
-};
-
-struct SinglePosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (c->glyph_set, hb_first)
- ;
-
- if (!it) return;
-
- unsigned sub_length = valueFormat.get_len ();
- const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
-
- for (unsigned i : + it
- | hb_map (hb_second))
- valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
-
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (likely (index >= valueCount)) return_trace (false);
-
- valueFormat.apply_value (c, this,
- &values[index * valueFormat.get_len ()],
- buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- auto out = c->extend_min (this);
- if (unlikely (!out)) return;
- if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
- if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
-
- + it
- | hb_map (hb_second)
- | hb_apply ([&] (hb_array_t<const Value> _)
- { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
- ;
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned sub_length = valueFormat.get_len ();
- auto values_array = values.as_array (valueCount * sub_length);
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
- {
- return hb_pair (glyph_map[_.first],
- values_array.sub_array (_.second * sub_length,
- sub_length));
- })
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_values (c, this, values, valueCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- HBUINT16 valueCount; /* Number of ValueRecords */
- ValueRecord values; /* Array of ValueRecords--positioning
- * values applied to glyphs */
- public:
- DEFINE_SIZE_ARRAY (8, values);
-};
-
-struct SinglePos
-{
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned get_format (Iterator glyph_val_iter_pairs)
- {
- hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
-
- for (const auto iter : glyph_val_iter_pairs)
- for (const auto _ : hb_zip (iter.second, first_val_iter))
- if (_.first != _.second)
- return 2;
-
- return 1;
- }
-
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup* src,
- Iterator glyph_val_iter_pairs,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (u.format))) return;
- unsigned format = 2;
- ValueFormat new_format = src->get_value_format ();
-
- if (glyph_val_iter_pairs)
- {
- format = get_format (glyph_val_iter_pairs);
- new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
- }
-
- u.format = format;
- switch (u.format) {
- case 1: u.format1.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- case 2: u.format2.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- default:return;
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- SinglePosFormat1 format1;
- SinglePosFormat2 format2;
- } u;
-};
-
-template<typename Iterator, typename SrcLookup>
-static void
-SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
-
-
-struct PairValueRecord
-{
- friend struct PairSet;
-
- int cmp (hb_codepoint_t k) const
- { return secondGlyph.cmp (k); }
-
- struct context_t
- {
- const void *base;
- const ValueFormat *valueFormats;
- const ValueFormat *newFormats;
- unsigned len1; /* valueFormats[0].get_len() */
- const hb_map_t *glyph_map;
- const hb_map_t *layout_variation_idx_map;
- };
-
- bool subset (hb_subset_context_t *c,
- context_t *closure) const
- {
- TRACE_SERIALIZE (this);
- auto *s = c->serializer;
- auto *out = s->start_embed (*this);
- if (unlikely (!s->extend_min (out))) return_trace (false);
-
- out->secondGlyph = (*closure->glyph_map)[secondGlyph];
-
- closure->valueFormats[0].copy_values (s,
- closure->newFormats[0],
- closure->base, &values[0],
- closure->layout_variation_idx_map);
- closure->valueFormats[1].copy_values (s,
- closure->newFormats[1],
- closure->base,
- &values[closure->len1],
- closure->layout_variation_idx_map);
-
- return_trace (true);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const ValueFormat *valueFormats,
- const void *base) const
- {
- unsigned record1_len = valueFormats[0].get_len ();
- unsigned record2_len = valueFormats[1].get_len ();
- const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
-
- if (valueFormats[0].has_device ())
- valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
-
- if (valueFormats[1].has_device ())
- valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
- }
-
- bool intersects (const hb_set_t& glyphset) const
- {
- return glyphset.has(secondGlyph);
- }
-
- const Value* get_values_1 () const
- {
- return &values[0];
- }
-
- const Value* get_values_2 (ValueFormat format1) const
- {
- return &values[format1.get_len ()];
- }
-
- protected:
- HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
- * pair--first glyph is listed in the
- * Coverage table */
- ValueRecord values; /* Positioning data for the first glyph
- * followed by for second glyph */
- public:
- DEFINE_SIZE_ARRAY (2, values);
-};
-
-struct PairSet
-{
- friend struct PairPosFormat1;
-
- bool intersects (const hb_set_t *glyphs,
- const ValueFormat *valueFormats) const
- {
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- {
- if (glyphs->has (record->secondGlyph))
- return true;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- return false;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c,
- const ValueFormat *valueFormats) const
- {
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- c->input->add_array (&record->secondGlyph, len, record_size);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const ValueFormat *valueFormats) const
- {
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len;
- for (unsigned i = 0; i < count; i++)
- {
- if (c->glyph_set->has (record->secondGlyph))
- { record->collect_variation_indices (c, valueFormats, this); }
-
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- bool apply (hb_ot_apply_context_t *c,
- const ValueFormat *valueFormats,
- unsigned int pos) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
- &firstPairValueRecord,
- len,
- record_size);
- if (record)
- {
- bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
- bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, pos + 1);
- if (len2)
- pos++;
- buffer->idx = pos;
- return_trace (true);
- }
- buffer->unsafe_to_concat (buffer->idx, pos + 1);
- return_trace (false);
- }
-
- bool subset (hb_subset_context_t *c,
- const ValueFormat valueFormats[2],
- const ValueFormat newFormats[2]) const
- {
- TRACE_SUBSET (this);
- auto snap = c->serializer->snapshot ();
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->len = 0;
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
-
- PairValueRecord::context_t context =
- {
- this,
- valueFormats,
- newFormats,
- len1,
- &glyph_map,
- c->plan->layout_variation_idx_map
- };
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len, num = 0;
- for (unsigned i = 0; i < count; i++)
- {
- if (glyphset.has (record->secondGlyph)
- && record->subset (c, &context)) num++;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
-
- out->len = num;
- if (!num) c->serializer->revert (snap);
- return_trace (num);
- }
-
- struct sanitize_closure_t
- {
- const ValueFormat *valueFormats;
- unsigned int len1; /* valueFormats[0].get_len() */
- unsigned int stride; /* 1 + len1 + len2 */
- };
-
- bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && c->check_range (&firstPairValueRecord,
- len,
- HBUINT16::static_size,
- closure->stride))) return_trace (false);
-
- unsigned int count = len;
- const PairValueRecord *record = &firstPairValueRecord;
- return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
- closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
- }
-
- protected:
- HBUINT16 len; /* Number of PairValueRecords */
- PairValueRecord firstPairValueRecord;
- /* Array of PairValueRecords--ordered
- * by GlyphID of the second glyph */
- public:
- DEFINE_SIZE_MIN (2);
-};
-
-struct PairPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, pairSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
- { return (this+_).intersects (glyphs, valueFormat); })
- | hb_any
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
-
- auto it =
- + hb_zip (this+coverage, pairSet)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- if (!it) return;
- + it
- | hb_map (hb_add (this))
- | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned int count = pairSet.len;
- for (unsigned int i = 0; i < count; i++)
- (this+pairSet[i]).collect_glyphs (c, valueFormat);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
- out->valueFormat[0] = valueFormat[0];
- out->valueFormat[1] = valueFormat[1];
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
- out->valueFormat[0] = newFormats.first;
- out->valueFormat[1] = newFormats.second;
- }
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
-
- + hb_zip (this+coverage, pairSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
- {
- auto snap = c->serializer->snapshot ();
- auto *o = out->pairSet.serialize_append (c->serializer);
- if (unlikely (!o)) return false;
- bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
- if (!ret)
- {
- out->pairSet.pop ();
- c->serializer->revert (snap);
- }
- return ret;
- },
- hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
-
- return_trace (bool (new_coverage));
- }
-
-
- hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
- {
- unsigned len1 = valueFormat[0].get_len ();
- unsigned len2 = valueFormat[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
-
- unsigned format1 = 0;
- unsigned format2 = 0;
- for (const Offset16To<PairSet>& _ :
- + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
- {
- const PairSet& set = (this + _);
- const PairValueRecord *record = &set.firstPairValueRecord;
-
- for (unsigned i = 0; i < set.len; i++)
- {
- if (record->intersects (glyphset))
- {
- format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
- format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
- }
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
-
- if (!c->check_struct (this)) return_trace (false);
-
- unsigned int len1 = valueFormat[0].get_len ();
- unsigned int len2 = valueFormat[1].get_len ();
- PairSet::sanitize_closure_t closure =
- {
- valueFormat,
- len1,
- 1 + len1 + len2
- };
-
- return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat[2]; /* [0] Defines the types of data in
- * ValueRecord1--for the first glyph
- * in the pair--may be zero (0) */
- /* [1] Defines the types of data in
- * ValueRecord2--for the second glyph
- * in the pair--may be zero (0) */
- Array16OfOffset16To<PairSet>
- pairSet; /* Array of PairSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (10, pairSet);
-};
-
-struct PairPosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+coverage).intersects (glyphs) &&
- (this+classDef2).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!intersects (c->glyph_set)) return;
- if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
-
- hb_set_t klass1_glyphs, klass2_glyphs;
- if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
- if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
-
- hb_set_t class1_set, class2_set;
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
- {
- if (!klass1_glyphs.has (cp)) class1_set.add (0);
- else
- {
- unsigned klass1 = (this+classDef1).get (cp);
- class1_set.add (klass1);
- }
- }
-
- class2_set.add (0);
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
- {
- unsigned klass2 = (this+classDef2).get (cp);
- class2_set.add (klass2);
- }
-
- if (class1_set.is_empty ()
- || class2_set.is_empty ()
- || (class2_set.get_population() == 1 && class2_set.has(0)))
- return;
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
- const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
- for (const unsigned class1_idx : class1_set.iter ())
- {
- for (const unsigned class2_idx : class2_set.iter ())
- {
- unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- if (valueFormat1.has_device ())
- valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
-
- if (valueFormat2.has_device ())
- valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
- }
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int record_len = len1 + len2;
-
- unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
- unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
- if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
- {
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
- return_trace (false);
- }
-
- const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-
- bool applied_first = false, applied_second = false;
-
-
- /* Isolate simple kerning and apply it half to each side.
- * Results in better cursor positinoing / underline drawing.
- *
- * Disabled, because causes issues... :-(
- * https://github.com/harfbuzz/harfbuzz/issues/3408
- * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
- */
-#ifndef HB_SPLIT_KERN
- if (0)
-#endif
- {
- if (!len2)
- {
- const hb_direction_t dir = buffer->props.direction;
- const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
- const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
- unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
- if (backward)
- mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
- /* Add Devices. */
- mask |= mask << 4;
-
- if (valueFormat1 & ~mask)
- goto bail;
-
- /* Is simple kern. Apply value on an empty position slot,
- * then split it between sides. */
-
- hb_glyph_position_t pos{};
- if (valueFormat1.apply_value (c, this, v, pos))
- {
- hb_position_t *src = &pos.x_advance;
- hb_position_t *dst1 = &buffer->cur_pos().x_advance;
- hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
- unsigned i = horizontal ? 0 : 1;
-
- hb_position_t kern = src[i];
- hb_position_t kern1 = kern >> 1;
- hb_position_t kern2 = kern - kern1;
-
- if (!backward)
- {
- dst1[i] += kern1;
- dst2[i] += kern2;
- dst2[i + 2] += kern2;
- }
- else
- {
- dst1[i] += kern1;
- dst1[i + 2] += src[i + 2] - kern2;
- dst2[i] += kern2;
- }
-
- applied_first = applied_second = kern != 0;
- goto success;
- }
- goto boring;
- }
- }
- bail:
-
-
- applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
- applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
-
- success:
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
- else
- boring:
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
-
-
- buffer->idx = skippy_iter.idx;
- if (len2)
- buffer->idx++;
-
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass1_map;
- out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
- out->class1Count = klass1_map.get_population ();
-
- hb_map_t klass2_map;
- out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
- out->class2Count = klass2_map.get_population ();
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- newFormats = compute_effective_value_formats (klass1_map, klass2_map);
-
- out->valueFormat1 = newFormats.first;
- out->valueFormat2 = newFormats.second;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
- valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
- }
- }
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- out->coverage.serialize_serialize (c->serializer, it);
- return_trace (out->class1Count && out->class2Count && bool (it));
- }
-
-
- hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
- const hb_map_t& klass2_map) const
- {
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- unsigned format1 = 0;
- unsigned format2 = 0;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
- format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && coverage.sanitize (c, this)
- && classDef1.sanitize (c, this)
- && classDef2.sanitize (c, this))) return_trace (false);
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int stride = len1 + len2;
- unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
- unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
- return_trace (c->check_range ((const void *) values,
- count,
- record_size) &&
- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat1; /* ValueRecord definition--for the
- * first glyph of the pair--may be zero
- * (0) */
- ValueFormat valueFormat2; /* ValueRecord definition--for the
- * second glyph of the pair--may be
- * zero (0) */
- Offset16To<ClassDef>
- classDef1; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the first glyph of the pair */
- Offset16To<ClassDef>
- classDef2; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the second glyph of the pair */
- HBUINT16 class1Count; /* Number of classes in ClassDef1
- * table--includes Class0 */
- HBUINT16 class2Count; /* Number of classes in ClassDef2
- * table--includes Class0 */
- ValueRecord values; /* Matrix of value pairs:
- * class1-major, class2-minor,
- * Each entry has value1 and value2 */
- public:
- DEFINE_SIZE_ARRAY (16, values);
-};
-
-struct PairPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- PairPosFormat1 format1;
- PairPosFormat2 format2;
- } u;
-};
-
-
-struct EntryExitRecord
-{
- friend struct CursivePosFormat1;
-
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+entryAnchor).collect_variation_indices (c);
- (src_base+exitAnchor).collect_variation_indices (c);
- }
-
- EntryExitRecord* subset (hb_subset_context_t *c,
- const void *src_base) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
- out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
- return_trace (out);
- }
-
- protected:
- Offset16To<Anchor>
- entryAnchor; /* Offset to EntryAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- Offset16To<Anchor>
- exitAnchor; /* Offset to ExitAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
-
-struct CursivePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
-
- const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
- if (!this_record.entryAnchor) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!prev_record.exitAnchor)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int i = skippy_iter.idx;
- unsigned int j = buffer->idx;
-
- buffer->unsafe_to_break (i, j);
- float entry_x, entry_y, exit_x, exit_y;
- (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
-
- hb_glyph_position_t *pos = buffer->pos;
-
- hb_position_t d;
- /* Main-direction adjustment */
- switch (c->direction) {
- case HB_DIRECTION_LTR:
- pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
-
- d = roundf (entry_x) + pos[j].x_offset;
- pos[j].x_advance -= d;
- pos[j].x_offset -= d;
- break;
- case HB_DIRECTION_RTL:
- d = roundf (exit_x) + pos[i].x_offset;
- pos[i].x_advance -= d;
- pos[i].x_offset -= d;
-
- pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
- break;
- case HB_DIRECTION_TTB:
- pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
-
- d = roundf (entry_y) + pos[j].y_offset;
- pos[j].y_advance -= d;
- pos[j].y_offset -= d;
- break;
- case HB_DIRECTION_BTT:
- d = roundf (exit_y) + pos[i].y_offset;
- pos[i].y_advance -= d;
- pos[i].y_offset -= d;
-
- pos[j].y_advance = roundf (entry_y);
- break;
- case HB_DIRECTION_INVALID:
- default:
- break;
- }
-
- /* Cross-direction adjustment */
-
- /* We attach child to parent (think graph theory and rooted trees whereas
- * the root stays on baseline and each node aligns itself against its
- * parent.
- *
- * Optimize things for the case of RightToLeft, as that's most common in
- * Arabic. */
- unsigned int child = i;
- unsigned int parent = j;
- hb_position_t x_offset = entry_x - exit_x;
- hb_position_t y_offset = entry_y - exit_y;
- if (!(c->lookup_props & LookupFlag::RightToLeft))
- {
- unsigned int k = child;
- child = parent;
- parent = k;
- x_offset = -x_offset;
- y_offset = -y_offset;
- }
-
- /* If child was already connected to someone else, walk through its old
- * chain and reverse the link direction, such that the whole tree of its
- * previous connection now attaches to new parent. Watch out for case
- * where new parent is on the path from old chain...
- */
- reverse_cursive_minor_offset (pos, child, c->direction, parent);
-
- pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
- pos[child].attach_chain() = (int) parent - (int) child;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
- pos[child].y_offset = y_offset;
- else
- pos[child].x_offset = x_offset;
-
- /* If parent was attached to child, separate them.
- * https://github.com/harfbuzz/harfbuzz/issues/2469
- */
- if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
- pos[parent].attach_chain() = 0;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_subset_context_t *c,
- Iterator it,
- const void *src_base)
- {
- if (unlikely (!c->serializer->extend_min ((*this)))) return;
- this->format = 1;
- this->entryExitRecord.len = it.len ();
-
- for (const EntryExitRecord& entry_record : + it
- | hb_map (hb_second))
- entry_record.subset (c, src_base);
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c->serializer, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- auto it =
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
- { return hb_pair (glyph_map[p.first], p.second);})
- ;
-
- bool ret = bool (it);
- out->serialize (c, it, this);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- Array16Of<EntryExitRecord>
- entryExitRecord; /* Array of EntryExit records--in
- * Coverage Index order */
- public:
- DEFINE_SIZE_ARRAY (6, entryExitRecord);
-};
-
-struct CursivePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CursivePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix BaseArray; /* base-major--
- * in order of BaseCoverage Index--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */)
-{
- hb_set_t orig_classes;
-
- + hb_zip (mark_coverage, mark_array)
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- | hb_map (&MarkRecord::get_class)
- | hb_sink (orig_classes)
- ;
-
- unsigned idx = 0;
- for (auto klass : orig_classes.iter ())
- {
- if (klass_mapping->has (klass)) continue;
- klass_mapping->set (klass, idx);
- idx++;
- }
-}
-
-struct MarkBasePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+baseCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : base_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
- (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
- /* Now we search backwards for a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- do {
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We only want to attach to the first of a MultipleSubst sequence.
- * https://github.com/harfbuzz/harfbuzz/issues/740
- * Reject others...
- * ...but stop if we find a mark in the MultipleSubst sequence:
- * https://github.com/harfbuzz/harfbuzz/issues/1020 */
- if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
- 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
- (skippy_iter.idx == 0 ||
- _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
- ))
- break;
- skippy_iter.reject ();
- } while (true);
-
- /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
- unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
- if (base_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + base_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : + base_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
-
- out->baseArray.serialize_subset (c, baseArray, this,
- base_iter.len (),
- base_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- baseCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- baseArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to MarkCoverage table--from
- * beginning of MarkBasePos subtable */
- Offset16To<Coverage>
- baseCoverage; /* Offset to BaseCoverage table--from
- * beginning of MarkBasePos subtable */
- HBUINT16 classCount; /* Number of classes defined for marks */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkBasePos subtable */
- Offset16To<BaseArray>
- baseArray; /* Offset to BaseArray table--from
- * beginning of MarkBasePos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkBasePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkBasePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix LigatureAttach; /* component-major--
- * in order of writing direction--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
-struct LigatureArray : List16OfOffset16To<LigatureAttach>
-{
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- unsigned class_count,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- for (const auto _ : + hb_zip (coverage, *this)
- | hb_filter (glyphset, hb_first))
- {
- auto *matrix = out->serialize_append (c->serializer);
- if (unlikely (!matrix)) return_trace (false);
-
- const LigatureAttach& src = (this + _.second);
- auto indexes =
- + hb_range (src.rows * class_count)
- | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
- ;
- matrix->serialize_subset (c,
- _.second,
- this,
- src.rows,
- indexes);
- }
- return_trace (this->len);
- }
-};
-
-struct MarkLigPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+ligatureCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned ligcount = (this+ligatureArray).len;
- auto lig_iter =
- + hb_zip (this+ligatureCoverage, hb_range (ligcount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- const LigatureArray& lig_array = this+ligatureArray;
- for (const unsigned i : lig_iter)
- {
- hb_sorted_vector_t<unsigned> lig_indexes;
- unsigned row_count = lig_array[i].rows;
- for (unsigned row : + hb_range (row_count))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (lig_indexes)
- ;
- }
-
- lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
- /* Now we search backwards for a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
- unsigned int j = skippy_iter.idx;
- unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
- if (lig_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- const LigatureArray& lig_array = this+ligatureArray;
- const LigatureAttach& lig_attach = lig_array[lig_index];
-
- /* Find component to attach to */
- unsigned int comp_count = lig_attach.rows;
- if (unlikely (!comp_count))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We must now check whether the ligature ID of the current mark glyph
- * is identical to the ligature ID of the found ligature. If yes, we
- * can directly use the component index. If not, we attach the mark
- * glyph to the last component of the ligature. */
- unsigned int comp_index;
- unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
- if (lig_id && lig_id == mark_id && mark_comp > 0)
- comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
- else
- comp_index = comp_count - 1;
-
- return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- auto new_mark_coverage =
- + mark_iter
- | hb_map_retains_sorting (hb_first)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- auto new_ligature_coverage =
- + hb_iter (this + ligatureCoverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
- return_trace (false);
-
- out->ligatureArray.serialize_subset (c, ligatureArray, this,
- hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- ligatureCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- ligatureArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to Mark Coverage table--from
- * beginning of MarkLigPos subtable */
- Offset16To<Coverage>
- ligatureCoverage; /* Offset to Ligature Coverage
- * table--from beginning of MarkLigPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkLigPos subtable */
- Offset16To<LigatureArray>
- ligatureArray; /* Offset to LigatureArray table--from
- * beginning of MarkLigPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-
-struct MarkLigPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkLigPosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix Mark2Array; /* mark2-major--
- * in order of Mark2Coverage Index--,
- * mark1-minor--
- * ordered by class--zero-based. */
-
-struct MarkMarkPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+mark1Coverage).intersects (glyphs) &&
- (this+mark2Coverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
-
- unsigned mark2_count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2_count))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : mark2_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
- (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+mark1Coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark1_index == NOT_COVERED)) return_trace (false);
-
- /* now we search backwards for a suitable mark glyph until a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int j = skippy_iter.idx;
-
- unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
- unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
-
- if (likely (id1 == id2))
- {
- if (id1 == 0) /* Marks belonging to the same base. */
- goto good;
- else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
- goto good;
- }
- else
- {
- /* If ligature ids don't match, it may be the case that one of the marks
- * itself is a ligature. In which case match. */
- if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
- goto good;
- }
-
- /* Didn't match. */
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
-
- good:
- unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
- if (mark2_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark1_iter =
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark1_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->mark1Array.serialize_subset (c, mark1Array, this,
- (this+mark1Coverage).iter (),
- &klass_mapping);
-
- unsigned mark2count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2count))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + mark2_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : + mark2_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
-
- out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- mark1Coverage.sanitize (c, this) &&
- mark2Coverage.sanitize (c, this) &&
- mark1Array.sanitize (c, this) &&
- mark2Array.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- mark1Coverage; /* Offset to Combining Mark1 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- Offset16To<Coverage>
- mark2Coverage; /* Offset to Combining Mark2 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- mark1Array; /* Offset to Mark1Array table--from
- * beginning of MarkMarkPos subtable */
- Offset16To<Mark2Array>
- mark2Array; /* Offset to Mark2Array table--from
- * beginning of MarkMarkPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkMarkPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkMarkPosFormat1 format1;
- } u;
-};
-
-
-struct ContextPos : Context {};
-
-struct ChainContextPos : ChainContext {};
-
-struct ExtensionPos : Extension<ExtensionPos>
-{
- typedef struct PosLookupSubTable SubTable;
-};
-
-
-
-/*
- * PosLookup
- */
-
-
-struct PosLookupSubTable
-{
- friend struct Lookup;
- friend struct PosLookup;
-
- enum Type {
- Single = 1,
- Pair = 2,
- Cursive = 3,
- MarkBase = 4,
- MarkLig = 5,
- MarkMark = 6,
- Context = 7,
- ChainContext = 8,
- Extension = 9
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
- case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
- case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
- case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
- case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
- case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SinglePos single;
- PairPos pair;
- CursivePos cursive;
- MarkBasePos markBase;
- MarkLigPos markLig;
- MarkMarkPos markMark;
- ContextPos context;
- ChainContextPos chainContext;
- ExtensionPos extension;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct PosLookup : Lookup
-{
- typedef struct PosLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- bool is_reverse () const
- {
- return false;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- { return dispatch (c); }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- template <typename context_t>
- static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GPOS -- Glyph Positioning
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
- */
-
-struct GPOS : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
-
- const PosLookup& get_lookup (unsigned int i) const
- { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
-
- static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
- return GSUBGPOS::subset<PosLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<PosLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
- {
- if (!c->gpos_lookups->has (i)) continue;
- const PosLookup &l = get_lookup (i);
- l.dispatch (c);
- }
- }
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
-};
-
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
-{
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- /* Stop if we see new parent in the chain. */
- if (j == new_parent)
- return;
-
- reverse_cursive_minor_offset (pos, j, direction, new_parent);
-
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[j].y_offset = -pos[i].y_offset;
- else
- pos[j].x_offset = -pos[i].x_offset;
-
- pos[j].attach_chain() = -chain;
- pos[j].attach_type() = type;
-}
-static void
-propagate_attachment_offsets (hb_glyph_position_t *pos,
- unsigned int len,
- unsigned int i,
- hb_direction_t direction)
-{
- /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
- * offset of glyph they are attached to. */
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- if (unlikely (j >= len))
- return;
-
- propagate_attachment_offsets (pos, len, j, direction);
-
- assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
-
- if (type & ATTACH_TYPE_CURSIVE)
- {
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[i].y_offset += pos[j].y_offset;
- else
- pos[i].x_offset += pos[j].x_offset;
- }
- else /*if (type & ATTACH_TYPE_MARK)*/
- {
- pos[i].x_offset += pos[j].x_offset;
- pos[i].y_offset += pos[j].y_offset;
-
- assert (j < i);
- if (HB_DIRECTION_IS_FORWARD (direction))
- for (unsigned int k = j; k < i; k++) {
- pos[i].x_offset -= pos[k].x_advance;
- pos[i].y_offset -= pos[k].y_advance;
- }
- else
- for (unsigned int k = j + 1; k < i + 1; k++) {
- pos[i].x_offset += pos[k].x_advance;
- pos[i].y_offset += pos[k].y_advance;
- }
- }
-}
-
-void
-GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
-}
-
-void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
-{
- //_hb_buffer_assert_gsubgpos_vars (buffer);
-}
-
-void
-GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
-{
- _hb_buffer_assert_gsubgpos_vars (buffer);
-
- unsigned int len;
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
- hb_direction_t direction = buffer->props.direction;
-
- /* Handle attachments */
- if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
- for (unsigned i = 0; i < len; i++)
- propagate_attachment_offsets (pos, len, i, direction);
-
- if (unlikely (font->slant))
- {
- for (unsigned i = 0; i < len; i++)
- if (unlikely (pos[i].y_offset))
- pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
- }
-}
-
-
-struct GPOS_accelerator_t : GPOS::accelerator_t {
- GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {}
-};
-
+using Layout::GPOS_impl::PosLookup;
+// TODO(garretrieger): Move into new layout directory.
/* Out-of-class implementation for methods recursing */
-
#ifndef HB_NO_OT_LAYOUT
template <typename context_t>
/*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
@@ -3121,13 +45,16 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+PosLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+template <>
+inline bool PosLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
@@ -3141,7 +68,6 @@ template <typename context_t>
}
#endif
-
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
index bef381430b..462542025b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -59,13 +59,16 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+SubstLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+template <>
+inline bool SubstLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index c9750ff63b..31da498652 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -109,14 +109,10 @@ struct hb_closure_context_t :
{
done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
- if (!done_lookups_glyph_set->get (lookup_index))
+ if (!done_lookups_glyph_set->has (lookup_index))
{
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
- {
- hb_set_destroy (empty_set);
+ if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return true;
- }
}
hb_set_clear (done_lookups_glyph_set->get (lookup_index));
@@ -165,21 +161,19 @@ struct hb_closure_context_t :
hb_set_t *glyphs;
hb_set_t output[1];
hb_vector_t<hb_set_t> active_glyphs_stack;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
unsigned int nesting_level_left;
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_map_t *done_lookups_glyph_count_,
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
- recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
done_lookups_glyph_count (done_lookups_glyph_count_),
- done_lookups_glyph_set (done_lookups_glyph_set_),
- lookup_count (0)
+ done_lookups_glyph_set (done_lookups_glyph_set_)
{}
~hb_closure_context_t () { flush (); }
@@ -197,8 +191,8 @@ struct hb_closure_context_t :
private:
hb_map_t *done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set;
- unsigned int lookup_count;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
+ unsigned int lookup_count = 0;
};
@@ -400,7 +394,6 @@ struct hb_collect_coverage_context_t :
set_t *set;
};
-
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{
@@ -416,7 +409,7 @@ struct hb_ot_apply_context_t :
match_func (nullptr),
match_data (nullptr) {}
- typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+ typedef bool (*match_func_t) (hb_glyph_info_t &info, const HBUINT16 &value, const void *data);
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
@@ -434,7 +427,7 @@ struct hb_ot_apply_context_t :
MATCH_MAYBE
};
- may_match_t may_match (const hb_glyph_info_t &info,
+ may_match_t may_match (hb_glyph_info_t &info,
const HBUINT16 *glyph_data) const
{
if (!(info.mask & mask) ||
@@ -442,7 +435,7 @@ struct hb_ot_apply_context_t :
return MATCH_NO;
if (match_func)
- return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+ return match_func (info, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
@@ -530,7 +523,7 @@ struct hb_ot_apply_context_t :
while (idx + num_items < end)
{
idx++;
- const hb_glyph_info_t &info = c->buffer->info[idx];
+ hb_glyph_info_t &info = c->buffer->info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
@@ -563,7 +556,7 @@ struct hb_ot_apply_context_t :
while (idx > num_items - 1)
{
idx--;
- const hb_glyph_info_t &info = c->buffer->out_info[idx];
+ hb_glyph_info_t &info = c->buffer->out_info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
@@ -611,7 +604,10 @@ struct hb_ot_apply_context_t :
return_t recurse (unsigned int sub_lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+ {
+ buffer->shaping_failed = true;
return default_return_value ();
+ }
nesting_level_left--;
bool ret = recurse_func (this, sub_lookup_index);
@@ -621,35 +617,34 @@ struct hb_ot_apply_context_t :
skipping_iterator_t iter_input, iter_context;
+ unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
const GDEF &gdef;
const VariationStore &var_store;
+ VariationStore::cache_t *var_store_cache;
hb_direction_t direction;
- hb_mask_t lookup_mask;
- unsigned int table_index; /* GSUB/GPOS */
- unsigned int lookup_index;
- unsigned int lookup_props;
- unsigned int nesting_level_left;
+ hb_mask_t lookup_mask = 1;
+ unsigned int lookup_index = (unsigned) -1;
+ unsigned int lookup_props = 0;
+ unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
bool has_glyph_classes;
- bool auto_zwnj;
- bool auto_zwj;
- bool per_syllable;
- bool random;
-
- uint32_t random_state;
-
+ bool auto_zwnj = true;
+ bool auto_zwj = true;
+ bool per_syllable = false;
+ bool random = false;
+ uint32_t random_state = 1;
+ unsigned new_syllables = (unsigned) -1;
hb_ot_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
- iter_input (), iter_context (),
+ table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
- recurse_func (nullptr),
gdef (
#ifndef HB_NO_OT_LAYOUT
*face->table.GDEF->table
@@ -658,18 +653,23 @@ struct hb_ot_apply_context_t :
#endif
),
var_store (gdef.get_var_store ()),
+ var_store_cache (
+#ifndef HB_NO_VAR
+ table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr
+#else
+ nullptr
+#endif
+ ),
direction (buffer_->props.direction),
- lookup_mask (1),
- table_index (table_index_),
- lookup_index ((unsigned int) -1),
- lookup_props (0),
- nesting_level_left (HB_MAX_NESTING_LEVEL),
- has_glyph_classes (gdef.has_glyph_classes ()),
- auto_zwnj (true),
- auto_zwj (true),
- per_syllable (false),
- random (false),
- random_state (1) { init_iters (); }
+ has_glyph_classes (gdef.has_glyph_classes ())
+ { init_iters (); }
+
+ ~hb_ot_apply_context_t ()
+ {
+#ifndef HB_NO_VAR
+ VariationStore::destroy_cache (var_store_cache);
+#endif
+ }
void init_iters ()
{
@@ -736,6 +736,9 @@ struct hb_ot_apply_context_t :
bool ligature = false,
bool component = false) const
{
+ if (new_syllables != (unsigned) -1)
+ buffer->cur().syllable() = new_syllables;
+
unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
@@ -790,8 +793,8 @@ struct hb_ot_apply_context_t :
};
-struct hb_get_subtables_context_t :
- hb_dispatch_context_t<hb_get_subtables_context_t>
+struct hb_accelerate_subtables_context_t :
+ hb_dispatch_context_t<hb_accelerate_subtables_context_t>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
@@ -800,15 +803,53 @@ struct hb_get_subtables_context_t :
return typed_obj->apply (c);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) )
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+ template <typename Type>
+ static inline bool apply_cached_to (const void *obj, OT::hb_ot_apply_context_t *c)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return apply_cached_ (typed_obj, c, hb_prioritize);
+ }
+
+ template <typename T>
+ static inline auto cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
+ template <typename T>
+ static inline bool cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+ template <typename Type>
+ static inline bool cache_func_to (const void *obj, OT::hb_ot_apply_context_t *c, bool enter)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return cache_func_ (typed_obj, c, enter, hb_prioritize);
+ }
+#endif
+
typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+ typedef bool (*hb_cache_func_t) (const void *obj, OT::hb_ot_apply_context_t *c, bool enter);
struct hb_applicable_t
{
+ friend struct hb_accelerate_subtables_context_t;
+ friend struct hb_ot_layout_lookup_accelerator_t;
+
template <typename T>
- void init (const T &obj_, hb_apply_func_t apply_func_)
+ void init (const T &obj_,
+ hb_apply_func_t apply_func_
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , hb_apply_func_t apply_cached_func_
+ , hb_cache_func_t cache_func_
+#endif
+ )
{
obj = &obj_;
apply_func = apply_func_;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ apply_cached_func = apply_cached_func_;
+ cache_func = cache_func_;
+#endif
digest.init ();
obj_.get_coverage ().collect_coverage (&digest);
}
@@ -817,38 +858,93 @@ struct hb_get_subtables_context_t :
{
return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ bool apply_cached (OT::hb_ot_apply_context_t *c) const
+ {
+ return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c);
+ }
+ bool cache_enter (OT::hb_ot_apply_context_t *c) const
+ {
+ return cache_func (obj, c, true);
+ }
+ void cache_leave (OT::hb_ot_apply_context_t *c) const
+ {
+ cache_func (obj, c, false);
+ }
+#endif
private:
const void *obj;
hb_apply_func_t apply_func;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ hb_apply_func_t apply_cached_func;
+ hb_cache_func_t cache_func;
+#endif
hb_set_digest_t digest;
};
typedef hb_vector_t<hb_applicable_t> array_t;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ template <typename T>
+ auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
+ template <typename T>
+ auto cache_cost (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( 0u )
+#endif
+
/* Dispatch interface. */
template <typename T>
return_t dispatch (const T &obj)
{
- hb_applicable_t *entry = array.push();
- entry->init (obj, apply_to<T>);
+ hb_applicable_t entry;
+
+ entry.init (obj,
+ apply_to<T>
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , apply_cached_to<T>
+ , cache_func_to<T>
+#endif
+ );
+
+ array.push (entry);
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ /* Cache handling
+ *
+ * We allow one subtable from each lookup to use a cache. The assumption
+ * being that multiple subtables of the same lookup cannot use a cache
+ * because the resources they would use will collide. As such, we ask
+ * each subtable to tell us how much it costs (which a cache would avoid),
+ * and we allocate the cache opportunity to the costliest subtable.
+ */
+ unsigned cost = cache_cost (obj, hb_prioritize);
+ if (cost > cache_user_cost && !array.in_error ())
+ {
+ cache_user_idx = array.length - 1;
+ cache_user_cost = cost;
+ }
+#endif
+
return hb_empty_t ();
}
static return_t default_return_value () { return hb_empty_t (); }
- hb_get_subtables_context_t (array_t &array_) :
- array (array_) {}
+ hb_accelerate_subtables_context_t (array_t &array_) :
+ array (array_) {}
array_t &array;
-};
-
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned cache_user_idx = (unsigned) -1;
+ unsigned cache_user_cost = 0;
+#endif
+};
typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs);
typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_glyph_info_t &info, const HBUINT16 &value, const void *data);
struct ContextClosureFuncs
{
@@ -863,6 +959,10 @@ struct ContextApplyFuncs
{
match_func_t match;
};
+struct ChainContextApplyFuncs
+{
+ match_func_t match[3];
+};
static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
@@ -939,19 +1039,30 @@ static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
}
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline bool match_glyph (hb_glyph_info_t &info, const HBUINT16 &value, const void *data HB_UNUSED)
{
- return glyph_id == value;
+ return info.codepoint == value;
}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_class (hb_glyph_info_t &info, const HBUINT16 &value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- return class_def.get_class (glyph_id) == value;
+ return class_def.get_class (info.codepoint) == value;
}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_class_cached (hb_glyph_info_t &info, const HBUINT16 &value, const void *data)
+{
+ unsigned klass = info.syllable();
+ if (klass < 255)
+ return klass == value;
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ klass = class_def.get_class (info.codepoint);
+ if (likely (klass < 255))
+ info.syllable() = klass;
+ return klass == value;
+}
+static inline bool match_coverage (hb_glyph_info_t &info, const HBUINT16 &value, const void *data)
{
const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
- return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+ return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
}
static inline bool would_match_input (hb_would_apply_context_t *c,
@@ -964,8 +1075,12 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
return false;
for (unsigned int i = 1; i < count; i++)
- if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+ {
+ hb_glyph_info_t info;
+ info.codepoint = c->glyphs[i];
+ if (likely (!match_func (info, input[i - 1], match_data)))
return false;
+ }
return true;
}
@@ -2125,19 +2240,54 @@ struct ContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+classDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const ClassDef &class_def = this+classDef;
- index = class_def.get_class (c->buffer->cur().codepoint);
- const RuleSet &rule_set = this+ruleSet[index];
+
struct ContextApplyLookupContext lookup_context = {
- {match_class},
+ {cached ? match_class_cached : match_class},
&class_def
};
+
+ if (cached && c->buffer->cur().syllable() < 255)
+ index = c->buffer->cur().syllable ();
+ else
+ {
+ index = class_def.get_class (c->buffer->cur().codepoint);
+ if (cached && index < 255)
+ c->buffer->cur().syllable() = index;
+ }
+ const RuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -2411,7 +2561,7 @@ struct ChainContextCollectGlyphsLookupContext
struct ChainContextApplyLookupContext
{
- ContextApplyFuncs funcs;
+ ChainContextApplyFuncs funcs;
const void *match_data[3];
};
@@ -2499,7 +2649,7 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
&& would_match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1]);
+ lookup_context.funcs.match[1], lookup_context.match_data[1]);
}
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
@@ -2518,11 +2668,11 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
if (!(match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1],
+ lookup_context.funcs.match[1], lookup_context.match_data[1],
&match_end, match_positions) && (end_index = match_end)
&& match_lookahead (c,
lookaheadCount, lookahead,
- lookup_context.funcs.match, lookup_context.match_data[2],
+ lookup_context.funcs.match[2], lookup_context.match_data[2],
match_end, &end_index)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
@@ -2532,7 +2682,7 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned start_index = c->buffer->out_len;
if (!match_backtrack (c,
backtrackCount, backtrack,
- lookup_context.funcs.match, lookup_context.match_data[0],
+ lookup_context.funcs.match[0], lookup_context.match_data[0],
&start_index))
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
@@ -2934,7 +3084,7 @@ struct ChainContextFormat1
{
const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return rule_set.would_apply (c, lookup_context);
@@ -2950,7 +3100,7 @@ struct ChainContextFormat1
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return_trace (rule_set.apply (c, lookup_context));
@@ -3134,7 +3284,7 @@ struct ChainContextFormat2
unsigned int index = input_class_def.get_class (c->glyphs[0]);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_class},
+ {{match_class, match_class, match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
@@ -3144,7 +3294,33 @@ struct ChainContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -3154,14 +3330,27 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- index = input_class_def.get_class (c->buffer->cur().codepoint);
- const ChainRuleSet &rule_set = this+ruleSet[index];
+ /* For ChainContextFormat2 we cache the LookaheadClassDef instead of InputClassDef.
+ * The reason is that most heavy fonts want to identify a glyph in context and apply
+ * a lookup to it. In this scenario, the length of the input sequence is one, whereas
+ * the lookahead / backtrack are typically longer. The one glyph in input sequence is
+ * looked-up below and no input glyph is looked up in individual rules, whereas the
+ * lookahead and backtrack glyphs are tried. Since we match lookahead before backtrack,
+ * we should cache lookahead. This decisions showed a 20% improvement in shaping of
+ * the Gulzar font.
+ */
+
struct ChainContextApplyLookupContext lookup_context = {
- {match_class},
+ {{cached && &backtrack_class_def == &input_class_def ? match_class_cached : match_class,
+ cached && &input_class_def == &lookahead_class_def ? match_class_cached : match_class,
+ cached ? match_class_cached : match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
};
+
+ index = input_class_def.get_class (c->buffer->cur().codepoint);
+ const ChainRuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -3359,7 +3548,7 @@ struct ChainContextFormat3
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return chain_context_would_apply_lookup (c,
@@ -3386,7 +3575,7 @@ struct ChainContextFormat3
const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return_trace (chain_context_apply_lookup (c,
@@ -3623,25 +3812,63 @@ struct hb_ot_layout_lookup_accelerator_t
lookup.collect_coverage (&digest);
subtables.init ();
- OT::hb_get_subtables_context_t c_get_subtables (subtables);
- lookup.dispatch (&c_get_subtables);
+ OT::hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
+ lookup.dispatch (&c_accelerate_subtables);
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ cache_user_idx = c_accelerate_subtables.cache_user_idx;
+ for (unsigned i = 0; i < subtables.length; i++)
+ if (i != cache_user_idx)
+ subtables[i].apply_cached_func = subtables[i].apply_func;
+#endif
}
void fini () { subtables.fini (); }
bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
- bool apply (hb_ot_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c, bool use_cache) const
{
- for (unsigned int i = 0; i < subtables.length; i++)
- if (subtables[i].apply (c))
- return true;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ if (use_cache)
+ {
+ for (unsigned int i = 0; i < subtables.length; i++)
+ if (subtables[i].apply_cached (c))
+ return true;
+ }
+ else
+#endif
+ {
+ for (unsigned int i = 0; i < subtables.length; i++)
+ if (subtables[i].apply (c))
+ return true;
+ }
return false;
}
+ bool cache_enter (OT::hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ return cache_user_idx != (unsigned) -1 &&
+ subtables[cache_user_idx].cache_enter (c);
+#else
+ return false;
+#endif
+ }
+ void cache_leave (OT::hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ subtables[cache_user_idx].cache_leave (c);
+#endif
+ }
+
+
private:
hb_set_digest_t digest;
- hb_get_subtables_context_t::array_t subtables;
+ hb_accelerate_subtables_context_t::array_t subtables;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned cache_user_idx = (unsigned) -1;
+#endif
};
struct GSUBGPOS
@@ -3721,6 +3948,8 @@ struct GSUBGPOS
hb_set_t visited_lookups, inactive_lookups;
OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+ c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
+
for (unsigned lookup_index : + hb_iter (lookup_indexes))
reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
@@ -3729,7 +3958,7 @@ struct GSUBGPOS
}
void prune_langsys (const hb_map_t *duplicate_feature_map,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
hb_set_t *new_feature_indexes /* OUT */) const
{
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
@@ -3787,7 +4016,7 @@ struct GSUBGPOS
hb_map_t *duplicate_feature_map /* OUT */) const
{
if (feature_indices->is_empty ()) return;
- hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
//find out duplicate features after subset
for (unsigned i : feature_indices->iter ())
{
@@ -3795,16 +4024,9 @@ struct GSUBGPOS
if (t == HB_MAP_VALUE_INVALID) continue;
if (!unique_features.has (t))
{
- hb_set_t* indices = hb_set_create ();
- if (unlikely (indices == hb_set_get_empty () ||
- !unique_features.set (t, indices)))
- {
- hb_set_destroy (indices);
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
+ if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return;
- }
- if (unique_features.get (t))
+ if (unique_features.has (t))
unique_features.get (t)->add (i);
duplicate_feature_map->set (i, i);
continue;
@@ -3849,9 +4071,6 @@ struct GSUBGPOS
duplicate_feature_map->set (i, i);
}
}
-
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
}
void prune_features (const hb_map_t *lookup_indices, /* IN */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index f4ea21a4f9..142c843dad 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -46,7 +46,7 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh"
#include "hb-ot-os2-table.hh"
@@ -55,6 +55,7 @@
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
using OT::Layout::GSUB::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-ot-layout
@@ -260,7 +261,6 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
{
_hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
_hb_glyph_info_clear_lig_props (&buffer->info[i]);
- buffer->info[i].syllable() = 0;
}
}
@@ -401,7 +401,7 @@ GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
}
bool
-OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face HB_UNUSED) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -1501,15 +1501,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
l.closure (&c, lookup_index);
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/**
@@ -1529,7 +1526,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const GSUB& gsub = *face->table.GSUB->table;
@@ -1551,13 +1548,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
}
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
glyphs_length != glyphs->get_population ());
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/*
- * OT::GPOS
+ * GPOS
*/
@@ -1588,7 +1582,7 @@ hb_ot_layout_has_positioning (hb_face_t *face)
void
hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_start (font, buffer);
+ GPOS::position_start (font, buffer);
}
@@ -1603,7 +1597,7 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_advances (font, buffer);
+ GPOS::position_finish_advances (font, buffer);
}
/**
@@ -1617,7 +1611,7 @@ hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_offsets (font, buffer);
+ GPOS::position_finish_offsets (font, buffer);
}
@@ -1652,7 +1646,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */)
{
- const OT::GPOS &gpos = *face->table.GPOS->table;
+ const GPOS &gpos = *face->table.GPOS->table;
const hb_tag_t tag = HB_TAG ('s','i','z','e');
unsigned int num_features = gpos.get_feature_count ();
@@ -1803,7 +1797,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
struct GSUBProxy
{
static constexpr unsigned table_index = 0u;
- static constexpr bool inplace = false;
+ static constexpr bool always_inplace = false;
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
@@ -1817,14 +1811,14 @@ struct GSUBProxy
struct GPOSProxy
{
static constexpr unsigned table_index = 1u;
- static constexpr bool inplace = true;
+ static constexpr bool always_inplace = true;
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
table (*face->table.GPOS->table),
accels (face->table.GPOS->accels) {}
- const OT::GPOS &table;
+ const GPOS &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
@@ -1833,6 +1827,8 @@ static inline bool
apply_forward (OT::hb_ot_apply_context_t *c,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
+ bool use_cache = accel.cache_enter (c);
+
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len && buffer->successful)
@@ -1842,7 +1838,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
- applied = accel.apply (c);
+ applied = accel.apply (c, use_cache);
}
if (applied)
@@ -1850,6 +1846,10 @@ apply_forward (OT::hb_ot_apply_context_t *c,
else
(void) buffer->next_glyph ();
}
+
+ if (use_cache)
+ accel.cache_leave (c);
+
return ret;
}
@@ -1864,7 +1864,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
- ret |= accel.apply (c);
+ ret |= accel.apply (c, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@@ -1890,13 +1890,13 @@ apply_string (OT::hb_ot_apply_context_t *c,
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->clear_output ();
buffer->idx = 0;
apply_forward (c, accel);
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->sync ();
}
else
@@ -1917,7 +1917,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const unsigned int table_index = proxy.table_index;
unsigned int i = 0;
OT::hb_ot_apply_context_t c (table_index, font, buffer);
- c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
+ c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index 75bba0bc50..6395f06670 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -589,13 +589,11 @@ _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
- HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
}
static inline void
_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
{
- HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
}
@@ -605,7 +603,6 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
HB_BUFFER_ASSERT_VAR (buffer, lig_props);
- HB_BUFFER_ASSERT_VAR (buffer, syllable);
}
/* Make sure no one directly touches our props... */
diff --git a/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh b/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
index c496dc2981..0e0f2d632a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
@@ -45,7 +45,7 @@ struct hb_ot_language_map_t
};
static const hb_ot_language_map_t
-hb_ms_language_map[] =
+_hb_ms_language_map[] =
{
{0x0001, "ar"}, /* ??? */
{0x0004, "zh"}, /* ??? */
@@ -298,7 +298,7 @@ hb_ms_language_map[] =
};
static const hb_ot_language_map_t
-hb_mac_language_map[] =
+_hb_mac_language_map[] =
{
{ 0, "en"}, /* English */
{ 1, "fr"}, /* French */
@@ -441,16 +441,16 @@ hb_language_t
_hb_ot_name_language_for_ms_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_ms_language_map,
- ARRAY_LENGTH (hb_ms_language_map));
+ _hb_ms_language_map,
+ ARRAY_LENGTH (_hb_ms_language_map));
}
hb_language_t
_hb_ot_name_language_for_mac_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_mac_language_map,
- ARRAY_LENGTH (hb_mac_language_map));
+ _hb_mac_language_map,
+ ARRAY_LENGTH (_hb_mac_language_map));
}
#endif /* HB_OT_NAME_LANGUAGE_STATIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
index d52367e9b1..01107aad67 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
@@ -156,7 +156,7 @@ struct NameRecord
};
static int
-_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
{
const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
@@ -169,8 +169,23 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
if (a->language == b->language) return 0;
if (!a->language) return -1;
if (!b->language) return +1;
- return strcmp (hb_language_to_string (a->language),
- hb_language_to_string (b->language));
+
+ const char *astr = hb_language_to_string (a->language);
+ const char *bstr = hb_language_to_string (b->language);
+
+ signed c = strcmp (astr, bstr);
+
+ if (!exact && c)
+ {
+ unsigned la = strlen (astr);
+ unsigned lb = strlen (bstr);
+ // 'a' is the user request, and 'b' is string in the font.
+ // If eg. user asks for "en-us" and font has "en", approve.
+ if (la > lb && astr[lb] == '-' && !strncmp (astr, bstr, lb))
+ return 0;
+ }
+
+ return c;
}
static int
@@ -178,7 +193,7 @@ _hb_ot_name_entry_cmp (const void *pa, const void *pb)
{
/* Compare by name_id, then language, then score, then index. */
- int v = _hb_ot_name_entry_cmp_key (pa, pb);
+ int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
if (v)
return v;
@@ -330,7 +345,18 @@ struct name
const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
this->names.length,
sizeof (hb_ot_name_entry_t),
- _hb_ot_name_entry_cmp_key);
+ _hb_ot_name_entry_cmp_key,
+ true);
+
+ if (!entry)
+ {
+ entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
+ this->names.length,
+ sizeof (hb_ot_name_entry_t),
+ _hb_ot_name_entry_cmp_key,
+ false);
+ }
+
if (!entry)
return -1;
diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
index f0035e2f04..3473afef54 100644
--- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
@@ -224,9 +224,11 @@ struct OS2
*max_cp = hb_min (0xFFFFu, codepoints->get_max ());
}
- /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */
+ /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
+ * https://docs.microsoft.com/en-us/typography/legacy/legacy_arabic_fonts */
enum font_page_t
{
+ FONT_PAGE_NONE = 0,
FONT_PAGE_HEBREW = 0xB100, /* Hebrew Windows 3.1 font page */
FONT_PAGE_SIMP_ARABIC = 0xB200, /* Simplified Arabic Windows 3.1 font page */
FONT_PAGE_TRAD_ARABIC = 0xB300, /* Traditional Arabic Windows 3.1 font page */
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
index 0f3cd8e24f..4d427e5431 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
@@ -52,16 +52,16 @@ HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
{
unsigned glyph_id = _.first;
unsigned new_index = _.second;
-
+
if (new_index < 258) continue;
if (copied_indices.has (new_index)) continue;
copied_indices.add (new_index);
-
+
hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
if (unlikely (!o)) return_trace (false);
if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
- memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
+ hb_memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
}
return_trace (true);
@@ -78,17 +78,19 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
post::accelerator_t _post (c->plan->source);
- hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
+ hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
unsigned old_index = glyphNameIndex[old_gid];
unsigned new_index;
+ const unsigned *new_index2;
if (old_index <= 257) new_index = old_index;
- else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
- else
+ else if (old_new_index_map.has (old_index, &new_index2))
{
+ new_index = *new_index2;
+ } else {
hb_bytes_t s = _post.find_glyph_name (old_gid);
new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1)
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
deleted file mode 100644
index 74bf3ca0fa..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ /dev/null
@@ -1,603 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-indic-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-
-#include "hb.hh"
-
-enum indic_syllable_type_t {
- indic_consonant_syllable,
- indic_vowel_syllable,
- indic_standalone_cluster,
- indic_symbol_cluster,
- indic_broken_cluster,
- indic_non_indic_cluster,
-};
-
-
-#line 45 "hb-ot-shape-complex-indic-machine.hh"
-#define indic_syllable_machine_ex_A 10u
-#define indic_syllable_machine_ex_C 1u
-#define indic_syllable_machine_ex_CM 17u
-#define indic_syllable_machine_ex_CS 19u
-#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define indic_syllable_machine_ex_H 4u
-#define indic_syllable_machine_ex_M 7u
-#define indic_syllable_machine_ex_N 3u
-#define indic_syllable_machine_ex_PLACEHOLDER 11u
-#define indic_syllable_machine_ex_RS 13u
-#define indic_syllable_machine_ex_Ra 16u
-#define indic_syllable_machine_ex_Repha 15u
-#define indic_syllable_machine_ex_SM 8u
-#define indic_syllable_machine_ex_Symbol 18u
-#define indic_syllable_machine_ex_V 2u
-#define indic_syllable_machine_ex_ZWJ 6u
-#define indic_syllable_machine_ex_ZWNJ 5u
-
-
-#line 65 "hb-ot-shape-complex-indic-machine.hh"
-static const unsigned char _indic_syllable_machine_trans_keys[] = {
- 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
- 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u,
- 4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u,
- 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u,
- 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u,
- 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u,
- 3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
- 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u,
- 5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u,
- 4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u,
- 3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
- 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u,
- 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u,
- 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u,
- 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
-};
-
-static const char _indic_syllable_machine_key_spans[] = {
- 1, 5, 3, 4, 5, 1, 1, 5,
- 10, 5, 1, 3, 4, 5, 1, 1,
- 5, 10, 10, 10, 1, 3, 4, 5,
- 1, 1, 5, 5, 10, 1, 3, 4,
- 5, 1, 1, 5, 5, 4, 1, 19,
- 15, 15, 14, 16, 6, 6, 1, 6,
- 16, 16, 16, 8, 7, 6, 7, 6,
- 8, 6, 15, 15, 15, 15, 14, 16,
- 15, 15, 14, 16, 6, 1, 6, 16,
- 16, 8, 7, 6, 7, 6, 6, 8,
- 6, 15, 15, 5, 15, 15, 14, 16,
- 15, 16, 6, 1, 6, 16, 16, 8,
- 7, 6, 15, 7, 6, 6, 8, 6,
- 15, 10, 5, 15, 15, 14, 16, 15,
- 16, 6, 1, 6, 16, 16, 8, 7,
- 6, 15, 7, 6, 6, 8, 6, 17,
- 15, 17, 10, 6, 1, 6, 16, 8,
- 6, 6, 1, 6, 16
-};
-
-static const short _indic_syllable_machine_index_offsets[] = {
- 0, 2, 8, 12, 17, 23, 25, 27,
- 33, 44, 50, 52, 56, 61, 67, 69,
- 71, 77, 88, 99, 110, 112, 116, 121,
- 127, 129, 131, 137, 143, 154, 156, 160,
- 165, 171, 173, 175, 181, 187, 192, 194,
- 214, 230, 246, 261, 278, 285, 292, 294,
- 301, 318, 335, 352, 361, 369, 376, 384,
- 391, 400, 407, 423, 439, 455, 471, 486,
- 503, 519, 535, 550, 567, 574, 576, 583,
- 600, 617, 626, 634, 641, 649, 656, 663,
- 672, 679, 695, 711, 717, 733, 749, 764,
- 781, 797, 814, 821, 823, 830, 847, 864,
- 873, 881, 888, 904, 912, 919, 926, 935,
- 942, 958, 969, 975, 991, 1007, 1022, 1039,
- 1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131,
- 1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200,
- 1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296,
- 1305, 1312, 1319, 1321, 1328
-};
-
-static const unsigned char _indic_syllable_machine_indicies[] = {
- 1, 0, 2, 3, 3, 4, 1, 0,
- 3, 3, 4, 0, 3, 3, 4, 1,
- 0, 5, 3, 3, 4, 1, 0, 6,
- 0, 7, 0, 8, 3, 3, 4, 1,
- 0, 2, 3, 3, 4, 1, 0, 0,
- 0, 0, 9, 0, 11, 12, 12, 13,
- 14, 10, 14, 10, 12, 12, 13, 10,
- 12, 12, 13, 14, 10, 15, 12, 12,
- 13, 14, 10, 16, 10, 17, 10, 18,
- 12, 12, 13, 14, 10, 11, 12, 12,
- 13, 14, 10, 10, 10, 10, 19, 10,
- 11, 12, 12, 13, 14, 10, 10, 10,
- 10, 20, 10, 22, 23, 23, 24, 25,
- 21, 21, 21, 21, 26, 21, 25, 21,
- 23, 23, 24, 27, 23, 23, 24, 25,
- 21, 28, 23, 23, 24, 25, 21, 29,
- 21, 30, 21, 22, 23, 23, 24, 25,
- 21, 31, 23, 23, 24, 25, 21, 33,
- 34, 34, 35, 36, 32, 32, 32, 32,
- 37, 32, 36, 32, 34, 34, 35, 32,
- 34, 34, 35, 36, 32, 38, 34, 34,
- 35, 36, 32, 39, 32, 40, 32, 33,
- 34, 34, 35, 36, 32, 41, 34, 34,
- 35, 36, 32, 23, 23, 24, 1, 0,
- 43, 42, 45, 46, 47, 48, 49, 50,
- 24, 25, 44, 51, 52, 52, 26, 44,
- 53, 54, 55, 56, 57, 44, 59, 60,
- 61, 62, 4, 1, 58, 63, 58, 58,
- 9, 58, 58, 58, 64, 58, 65, 60,
- 66, 66, 4, 1, 58, 63, 58, 58,
- 58, 58, 58, 58, 64, 58, 60, 66,
- 66, 4, 1, 58, 63, 58, 58, 58,
- 58, 58, 58, 64, 58, 45, 58, 58,
- 58, 67, 68, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 69, 69,
- 58, 1, 58, 63, 58, 63, 58, 58,
- 70, 58, 63, 58, 63, 58, 63, 58,
- 58, 58, 58, 63, 58, 45, 58, 71,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 45, 58,
- 58, 58, 69, 69, 58, 1, 58, 63,
- 58, 58, 58, 58, 58, 45, 58, 45,
- 58, 58, 58, 69, 68, 58, 1, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 72, 7, 73, 74, 4, 1, 58, 63,
- 58, 7, 73, 74, 4, 1, 58, 63,
- 58, 73, 73, 4, 1, 58, 63, 58,
- 75, 76, 76, 4, 1, 58, 63, 58,
- 67, 77, 58, 1, 58, 63, 58, 67,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 69, 77, 58, 1, 58, 63, 58, 59,
- 60, 66, 66, 4, 1, 58, 63, 58,
- 58, 58, 58, 58, 58, 64, 58, 59,
- 60, 61, 66, 4, 1, 58, 63, 58,
- 58, 9, 58, 58, 58, 64, 58, 79,
- 80, 81, 82, 13, 14, 78, 83, 78,
- 78, 20, 78, 78, 78, 84, 78, 85,
- 80, 86, 82, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 82, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 88, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 90,
- 80, 91, 92, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 93,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 86, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 94, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 83,
- 78, 78, 95, 78, 83, 78, 83, 78,
- 83, 78, 78, 78, 78, 83, 78, 87,
- 78, 96, 78, 94, 94, 78, 14, 78,
- 83, 78, 78, 78, 78, 78, 87, 78,
- 87, 78, 78, 78, 94, 94, 78, 14,
- 78, 83, 78, 78, 78, 78, 78, 87,
- 78, 97, 17, 98, 99, 13, 14, 78,
- 83, 78, 17, 98, 99, 13, 14, 78,
- 83, 78, 98, 98, 13, 14, 78, 83,
- 78, 100, 101, 101, 13, 14, 78, 83,
- 78, 88, 102, 78, 14, 78, 83, 78,
- 94, 94, 78, 14, 78, 83, 78, 88,
- 78, 94, 94, 78, 14, 78, 83, 78,
- 94, 102, 78, 14, 78, 83, 78, 90,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 90,
- 80, 91, 86, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 11,
- 12, 12, 13, 14, 78, 79, 80, 86,
- 82, 13, 14, 78, 83, 78, 78, 78,
- 78, 78, 78, 84, 78, 104, 48, 105,
- 105, 24, 25, 103, 51, 103, 103, 103,
- 103, 103, 103, 55, 103, 48, 105, 105,
- 24, 25, 103, 51, 103, 103, 103, 103,
- 103, 103, 55, 103, 106, 103, 103, 103,
- 107, 108, 103, 25, 103, 51, 103, 103,
- 103, 103, 103, 106, 103, 47, 48, 109,
- 110, 24, 25, 103, 51, 103, 103, 26,
- 103, 103, 103, 55, 103, 106, 103, 103,
- 103, 111, 108, 103, 25, 103, 51, 103,
- 103, 103, 103, 103, 106, 103, 51, 103,
- 103, 112, 103, 51, 103, 51, 103, 51,
- 103, 103, 103, 103, 51, 103, 106, 103,
- 113, 103, 111, 111, 103, 25, 103, 51,
- 103, 103, 103, 103, 103, 106, 103, 106,
- 103, 103, 103, 111, 111, 103, 25, 103,
- 51, 103, 103, 103, 103, 103, 106, 103,
- 114, 30, 115, 116, 24, 25, 103, 51,
- 103, 30, 115, 116, 24, 25, 103, 51,
- 103, 115, 115, 24, 25, 103, 51, 103,
- 47, 48, 105, 105, 24, 25, 103, 51,
- 103, 103, 103, 103, 103, 103, 55, 103,
- 117, 118, 118, 24, 25, 103, 51, 103,
- 107, 119, 103, 25, 103, 51, 103, 111,
- 111, 103, 25, 103, 51, 103, 107, 103,
- 111, 111, 103, 25, 103, 51, 103, 111,
- 119, 103, 25, 103, 51, 103, 47, 48,
- 109, 105, 24, 25, 103, 51, 103, 103,
- 26, 103, 103, 103, 55, 103, 22, 23,
- 23, 24, 25, 120, 120, 120, 120, 26,
- 120, 22, 23, 23, 24, 25, 120, 122,
- 123, 124, 125, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 128,
- 123, 125, 125, 35, 36, 121, 126, 121,
- 121, 121, 121, 121, 121, 127, 121, 123,
- 125, 125, 35, 36, 121, 126, 121, 121,
- 121, 121, 121, 121, 127, 121, 129, 121,
- 121, 121, 130, 131, 121, 36, 121, 126,
- 121, 121, 121, 121, 121, 129, 121, 122,
- 123, 124, 52, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 129,
- 121, 121, 121, 132, 131, 121, 36, 121,
- 126, 121, 121, 121, 121, 121, 129, 121,
- 126, 121, 121, 133, 121, 126, 121, 126,
- 121, 126, 121, 121, 121, 121, 126, 121,
- 129, 121, 134, 121, 132, 132, 121, 36,
- 121, 126, 121, 121, 121, 121, 121, 129,
- 121, 129, 121, 121, 121, 132, 132, 121,
- 36, 121, 126, 121, 121, 121, 121, 121,
- 129, 121, 135, 40, 136, 137, 35, 36,
- 121, 126, 121, 40, 136, 137, 35, 36,
- 121, 126, 121, 136, 136, 35, 36, 121,
- 126, 121, 122, 123, 125, 125, 35, 36,
- 121, 126, 121, 121, 121, 121, 121, 121,
- 127, 121, 138, 139, 139, 35, 36, 121,
- 126, 121, 130, 140, 121, 36, 121, 126,
- 121, 132, 132, 121, 36, 121, 126, 121,
- 130, 121, 132, 132, 121, 36, 121, 126,
- 121, 132, 140, 121, 36, 121, 126, 121,
- 45, 46, 47, 48, 109, 105, 24, 25,
- 103, 51, 52, 52, 26, 103, 103, 45,
- 55, 103, 59, 141, 61, 62, 4, 1,
- 58, 63, 58, 58, 9, 58, 58, 58,
- 64, 58, 45, 46, 47, 48, 142, 143,
- 24, 144, 58, 145, 58, 52, 26, 58,
- 58, 45, 55, 58, 22, 146, 146, 24,
- 144, 58, 63, 58, 58, 26, 58, 145,
- 58, 58, 147, 58, 145, 58, 145, 58,
- 145, 58, 58, 58, 58, 145, 58, 45,
- 58, 71, 22, 146, 146, 24, 144, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 149, 148, 150, 150, 148, 43, 148, 151,
- 148, 150, 150, 148, 43, 148, 151, 148,
- 151, 148, 148, 152, 148, 151, 148, 151,
- 148, 151, 148, 148, 148, 148, 151, 148,
- 45, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 52, 120, 120, 120, 120, 45,
- 120, 0
-};
-
-static const unsigned char _indic_syllable_machine_trans_targs[] = {
- 39, 45, 50, 2, 51, 5, 6, 53,
- 57, 58, 39, 67, 11, 73, 68, 14,
- 15, 75, 80, 81, 84, 39, 89, 21,
- 95, 90, 98, 39, 24, 25, 97, 103,
- 39, 112, 30, 118, 113, 121, 33, 34,
- 120, 126, 39, 137, 39, 40, 60, 85,
- 87, 105, 106, 91, 107, 127, 128, 99,
- 135, 140, 39, 41, 43, 8, 59, 46,
- 54, 42, 1, 44, 48, 0, 47, 49,
- 52, 3, 4, 55, 7, 56, 39, 61,
- 63, 18, 83, 69, 76, 62, 9, 64,
- 78, 71, 65, 17, 82, 66, 10, 70,
- 72, 74, 12, 13, 77, 16, 79, 39,
- 86, 26, 88, 101, 93, 19, 104, 20,
- 92, 94, 96, 22, 23, 100, 27, 102,
- 39, 39, 108, 110, 28, 35, 114, 122,
- 109, 111, 124, 116, 29, 115, 117, 119,
- 31, 32, 123, 36, 125, 129, 130, 134,
- 131, 132, 37, 133, 39, 136, 38, 138,
- 139
-};
-
-static const char _indic_syllable_machine_trans_actions[] = {
- 1, 0, 2, 0, 2, 0, 0, 2,
- 2, 2, 3, 2, 0, 2, 0, 0,
- 0, 2, 2, 2, 2, 4, 2, 0,
- 5, 0, 5, 6, 0, 0, 5, 2,
- 7, 2, 0, 2, 0, 2, 0, 0,
- 2, 2, 8, 0, 11, 2, 2, 5,
- 0, 12, 12, 0, 2, 5, 2, 5,
- 2, 0, 13, 2, 0, 0, 2, 0,
- 2, 2, 0, 2, 2, 0, 0, 2,
- 2, 0, 0, 0, 0, 2, 14, 2,
- 0, 0, 2, 0, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 0, 0,
- 2, 2, 0, 0, 0, 0, 2, 15,
- 5, 0, 5, 2, 2, 0, 5, 0,
- 0, 2, 5, 0, 0, 0, 0, 2,
- 16, 17, 2, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 0, 0, 2, 2,
- 0, 0, 0, 0, 2, 0, 18, 18,
- 0, 0, 0, 0, 19, 2, 0, 0,
- 0
-};
-
-static const char _indic_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const char _indic_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 10,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const short _indic_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 22, 22, 28, 22, 22,
- 22, 22, 22, 22, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 1, 43, 0,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 121, 121, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 104,
- 59, 59, 59, 59, 59, 59, 59, 149,
- 149, 149, 149, 149, 121
-};
-
-static const int indic_syllable_machine_start = 39;
-static const int indic_syllable_machine_first_final = 39;
-static const int indic_syllable_machine_error = -1;
-
-static const int indic_syllable_machine_en_main = 39;
-
-
-#line 46 "hb-ot-shape-complex-indic-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-indic-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_indic (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 440 "hb-ot-shape-complex-indic-machine.hh"
- {
- cs = indic_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 456 "hb-ot-shape-complex-indic-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const unsigned char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _indic_syllable_machine_from_state_actions[cs] ) {
- case 10:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 470 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- _keys = _indic_syllable_machine_trans_keys + (cs<<1);
- _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
-
- _slen = _indic_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
- ( info[p].indic_category()) <= _keys[1] ?
- ( info[p].indic_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _indic_syllable_machine_trans_targs[_trans];
-
- if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _indic_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 11:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 13:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
- break;
- case 14:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
- break;
- case 17:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
- break;
- case 19:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
- break;
- case 15:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_broken_cluster); }}
- break;
- case 16:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 1:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
- break;
- case 3:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
- break;
- case 7:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
- break;
- case 8:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
- break;
- case 4:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }}
- break;
- case 6:
-#line 1 "NONE"
- { switch( act ) {
- case 1:
- {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
- break;
- case 5:
- {{p = ((te))-1;} found_syllable (indic_broken_cluster); }
- break;
- case 6:
- {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
- break;
- }
- }
- break;
- case 18:
-#line 1 "NONE"
- {te = p+1;}
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {act = 1;}
- break;
- case 5:
-#line 1 "NONE"
- {te = p+1;}
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {act = 5;}
- break;
- case 12:
-#line 1 "NONE"
- {te = p+1;}
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {act = 6;}
- break;
-#line 573 "hb-ot-shape-complex-indic-machine.hh"
- }
-
-_again:
- switch ( _indic_syllable_machine_to_state_actions[cs] ) {
- case 9:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 582 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _indic_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-indic-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
deleted file mode 100644
index 326aa9f96e..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # IndicPositionalCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-indic.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-
-#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 17 chars; Avagraha */
-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 91 chars; Bindu */
-#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
-#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 59 chars; Cantillation_Mark */
-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2206 chars; Consonant */
-#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 14 chars; Consonant_Dead */
-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 70 chars; Consonant_Final */
-#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
-#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
-#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 31 chars; Consonant_Medial */
-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 22 chars; Consonant_Placeholder */
-#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 3 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 10 chars; Consonant_Prefixed */
-#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 94 chars; Consonant_Subjoined */
-#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 1 chars; Consonant_Succeeding_Repha */
-#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 8 chars; Consonant_With_Stacker */
-#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
-#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 12 chars; Invisible_Stacker */
-#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
-#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
-#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 32 chars; Nukta */
-#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 491 chars; Number */
-#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
-#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
-#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 25 chars; Pure_Killer */
-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
-#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
-#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */
-#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 27 chars; Virama */
-#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 35 chars; Visarga */
-#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 686 chars; Vowel_Dependent */
-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 486 chars; Vowel_Independent */
-
-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 352 chars; Bottom */
-#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
-#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 4 chars; Bottom_And_Right */
-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 64 chars; Left */
-#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 22 chars; Left_And_Right */
-#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
-#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 290 chars; Right */
-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 418 chars; Top */
-#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
-#define IMC_TBL INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT /* 2 chars; Top_And_Bottom_And_Left */
-#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
-#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */
-#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */
-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */
-
-#pragma GCC diagnostic pop
-
-#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-
-
-static const uint16_t indic_table[] = {
-
-
-#define indic_offset_0x0028u 0
-
-
- /* Basic Latin */
-
- /* 0028 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), _(x,x),
- /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x00b0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x),
-
-#define indic_offset_0x0900u 64
-
-
- /* Devanagari */
-
- /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
- /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
- /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B),
- /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0978 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
-
- /* Bengali */
-
- /* 0980 */ _(CP,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
- /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(SM,T), _(x,x),
-
- /* Gurmukhi */
-
- /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
- /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L),
- /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
- /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
- /* 0A50 */ _(x,x), _(Ca,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
- /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x),
- /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Gujarati */
-
- /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
- /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T),
- /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
- /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AF8 */ _(x,x), _(C,x), _(Ca,T), _(Ca,T), _(Ca,T), _(N,T), _(N,T), _(N,T),
-
- /* Oriya */
-
- /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
- /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,T), _(M,TR),
- /* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Tamil */
-
- /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
- /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x),
- /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x),
- /* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
- /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R),
- /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
- /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
- /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Telugu */
-
- /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(Bi,T), _(VI,x), _(VI,x), _(VI,x),
- /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,T), _(M,T),
- /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
- /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
- /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(CD,x), _(x,x), _(x,x),
- /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Kannada */
-
- /* 0C80 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
- /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
- /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(C,x), _(x,x),
- /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Malayalam */
-
- /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R), _(Bi,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D38 */ _(C,x), _(C,x), _(C,x), _(PK,T), _(PK,T), _(A,x), _(M,R), _(M,R),
- /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
- /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,T), _(x,x),
- /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R),
- /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
-
- /* Sinhala */
-
- /* 0D80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x),
- /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x),
- /* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
- /* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
- /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR),_(M,TLR), _(M,LR), _(M,R),
- /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1000u 1336
-
-
- /* Myanmar */
-
- /* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
- /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B),
- /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R),_(CM,TBL), _(CM,B), _(CM,B), _(C,x),
- /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(CP,x), _(x,x), _(x,x), _(CP,x), _(x,x),
- /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
- /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B),
- /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R),
- /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x),
- /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x),
- /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R),
- /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R),
- /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x),
-
-#define indic_offset_0x1780u 1496
-
-
- /* Khmer */
-
- /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
- /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
- /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
- /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
- /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(SM,T), _(x,x), _(x,x),
- /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1cd0u 1608
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O),
- /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x),
- /* 1CF0 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(Ca,T),_(CWS,x),_(CWS,x), _(Ca,R),
- /* 1CF8 */ _(Ca,x), _(Ca,x), _(CP,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2008u 1656
-
-
- /* General Punctuation */
-
- /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x),
- /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2070u 1672
-
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x),
- /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0xa8e0u 1696
-
-
- /* Devanagari Extended */
-
- /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(M,T),
-
-#define indic_offset_0xa9e0u 1728
-
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x),
- /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
-
-#define indic_offset_0xaa60u 1760
-
-
- /* Myanmar Extended-A */
-
- /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
-
-}; /* Table items: 1792; occupancy: 71% */
-
-uint16_t
-hb_indic_get_categories (hb_codepoint_t u)
-{
- switch (u >> 12)
- {
- case 0x0u:
- if (unlikely (u == 0x00A0u)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
- break;
-
- case 0x2u:
- if (unlikely (u == 0x25CCu)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
- break;
-
- default:
- break;
- }
- return _(x,x);
-}
-
-#undef _
-
-#undef ISC_A
-#undef ISC_Bi
-#undef ISC_BJN
-#undef ISC_Ca
-#undef ISC_C
-#undef ISC_CD
-#undef ISC_CF
-#undef ISC_CHL
-#undef ISC_CIP
-#undef ISC_CK
-#undef ISC_CM
-#undef ISC_CP
-#undef ISC_CPR
-#undef ISC_CPrf
-#undef ISC_CS
-#undef ISC_CSR
-#undef ISC_CWS
-#undef ISC_GM
-#undef ISC_IS
-#undef ISC_ZWJ
-#undef ISC_ML
-#undef ISC_ZWNJ
-#undef ISC_N
-#undef ISC_Nd
-#undef ISC_NJ
-#undef ISC_x
-#undef ISC_PK
-#undef ISC_RS
-#undef ISC_SM
-#undef ISC_TL
-#undef ISC_TM
-#undef ISC_V
-#undef ISC_Vs
-#undef ISC_Vo
-#undef ISC_M
-#undef ISC_VI
-
-#undef IMC_B
-#undef IMC_BL
-#undef IMC_BR
-#undef IMC_L
-#undef IMC_LR
-#undef IMC_x
-#undef IMC_O
-#undef IMC_R
-#undef IMC_T
-#undef IMC_TB
-#undef IMC_TBL
-#undef IMC_TBR
-#undef IMC_TL
-#undef IMC_TLR
-#undef IMC_TR
-#undef IMC_VOL
-
-#endif
-
-/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
deleted file mode 100644
index da77a2887c..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright © 2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_category() /* indic_category_t */
-#define indic_position() complex_var_u8_auxiliary() /* indic_position_t */
-
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
- OT_X = 0,
- OT_C = 1,
- OT_V = 2,
- OT_N = 3,
- OT_H = 4,
- OT_ZWNJ = 5,
- OT_ZWJ = 6,
- OT_M = 7,
- OT_SM = 8,
- /* OT_VD = 9, UNUSED; we use OT_A instead. */
- OT_A = 10,
- OT_PLACEHOLDER = 11,
- OT_DOTTEDCIRCLE = 12,
- OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
- OT_Coeng = 14, /* Khmer-style Virama. */
- OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
- OT_Ra = 16,
- OT_CM = 17, /* Consonant-Medial. */
- OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
- OT_CS = 19,
-
- /* The following are used by Khmer & Myanmar shapers. Defined
- * here for them to share. */
- OT_VAbv = 26,
- OT_VBlw = 27,
- OT_VPre = 28,
- OT_VPst = 29,
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
- * cannot happen in a consonant syllable. The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
- POS_START = 0,
-
- POS_RA_TO_BECOME_REPH = 1,
- POS_PRE_M = 2,
- POS_PRE_C = 3,
-
- POS_BASE_C = 4,
- POS_AFTER_MAIN = 5,
-
- POS_ABOVE_C = 6,
-
- POS_BEFORE_SUB = 7,
- POS_BELOW_C = 8,
- POS_AFTER_SUB = 9,
-
- POS_BEFORE_POST = 10,
- POS_POST_C = 11,
- POS_AFTER_POST = 12,
-
- POS_FINAL_C = 13,
- POS_SMVD = 14,
-
- POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
- INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
-
- INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
- INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
- INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
- INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS,
- INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng,
- INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
- INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
- INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
- INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */
- INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
- INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM,
- INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
- INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
- INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
- INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
- INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
- INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
- INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_END,
-
- INDIC_MATRA_CATEGORY_LEFT = POS_PRE_C,
- INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_C,
- INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_C,
- INDIC_MATRA_CATEGORY_RIGHT = POS_POST_C,
-
- /* These should resolve to the position of the last part of the split sequence. */
- INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_TOP,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
-
- INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
- INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
- ( \
- static_assert_expr (S < 255 && M < 255) + \
- ( S | \
- ( \
- ( \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
- S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
- S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
- S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
- S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
- false \
- ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
- ) << 8 \
- ) \
- ) \
- )
-
-HB_INTERNAL uint16_t
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
- return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u) POS_PRE_M
-#define MATRA_POS_RIGHT(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_POST : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_POST : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
- IS_GUJR(u) ? POS_AFTER_SUB : \
- IS_ORYA(u) ? POS_AFTER_MAIN : \
- IS_TAML(u) ? POS_AFTER_SUB : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_BOTTOM(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_SUB : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
- switch ((int) side)
- {
- case POS_PRE_C: return MATRA_POS_LEFT (u);
- case POS_POST_C: return MATRA_POS_RIGHT (u);
- case POS_ABOVE_C: return MATRA_POS_TOP (u);
- case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
- }
- return side;
-}
-
-/* XXX
- * This is a hack for now. We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
- 0x0930u, /* Devanagari */
- 0x09B0u, /* Bengali */
- 0x09F0u, /* Bengali */
- 0x0A30u, /* Gurmukhi */ /* No Reph */
- 0x0AB0u, /* Gujarati */
- 0x0B30u, /* Oriya */
- 0x0BB0u, /* Tamil */ /* No Reph */
- 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
- 0x0CB0u, /* Kannada */
- 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
-
- 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
- return hb_array (ra_chars).lfind (u);
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0xFFu);
- indic_position_t pos = (indic_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- */
-
- /* The following act more like the Bindus. */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
- cat = OT_SM;
- /* The following act like consonants. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
- 0x1CF5u, 0x1CF6u)))
- cat = OT_C;
- /* TODO: The following should only be allowed after a Visarga.
- * For now, just treat them like regular tone marks. */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
- cat = OT_A;
- /* TODO: The following should only be allowed after some of
- * the nasalization marks, maybe only for U+1CE9..U+1CF1.
- * For now, just treat them like tone marks. */
- else if (unlikely (u == 0x1CEDu))
- cat = OT_A;
- /* The following take marks in standalone clusters, similar to Avagraha. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
- 0x1CE9u, 0x1CECu,
- 0x1CEEu, 0x1CF1u)))
- {
- cat = OT_Symbol;
- static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
- }
- else if (unlikely (u == 0x0A51u))
- {
- /* https://github.com/harfbuzz/harfbuzz/issues/524 */
- cat = OT_M;
- pos = POS_BELOW_C;
- }
-
- /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
- * so the Indic shaper needs to know their categories. */
- else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
- else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
-
- else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */
-
- else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
- else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
- else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
- else if (unlikely (u == 0x0D04u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/3511 */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
- cat = OT_PLACEHOLDER;
- else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
- /*
- * Re-assign position.
- */
-
- if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
- {
- pos = POS_BASE_C;
- if (is_ra (u))
- cat = OT_Ra;
- }
- else if (cat == OT_M)
- {
- pos = matra_position_indic (u, pos);
- }
- else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
- {
- pos = POS_SMVD;
- }
-
- if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
- info.indic_category() = cat;
- info.indic_position() = pos;
-}
-
-struct hb_indic_would_substitute_feature_t
-{
- void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
- {
- zero_context = zero_context_;
- map->get_stage_lookups (0/*GSUB*/,
- map->get_feature_stage (0/*GSUB*/, feature_tag),
- &lookups, &count);
- }
-
- bool would_substitute (const hb_codepoint_t *glyphs,
- unsigned int glyphs_count,
- hb_face_t *face) const
- {
- for (unsigned int i = 0; i < count; i++)
- if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
- return true;
- return false;
- }
-
- private:
- const hb_ot_map_t::lookup_map_t *lookups;
- unsigned int count;
- bool zero_context;
-};
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
deleted file mode 100644
index c52f72f394..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
+++ /dev/null
@@ -1,396 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-khmer-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-
-#include "hb.hh"
-
-enum khmer_syllable_type_t {
- khmer_consonant_syllable,
- khmer_broken_cluster,
- khmer_non_khmer_cluster,
-};
-
-
-#line 42 "hb-ot-shape-complex-khmer-machine.hh"
-#define khmer_syllable_machine_ex_C 1u
-#define khmer_syllable_machine_ex_Coeng 14u
-#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define khmer_syllable_machine_ex_PLACEHOLDER 11u
-#define khmer_syllable_machine_ex_Ra 16u
-#define khmer_syllable_machine_ex_Robatic 20u
-#define khmer_syllable_machine_ex_V 2u
-#define khmer_syllable_machine_ex_VAbv 26u
-#define khmer_syllable_machine_ex_VBlw 27u
-#define khmer_syllable_machine_ex_VPre 28u
-#define khmer_syllable_machine_ex_VPst 29u
-#define khmer_syllable_machine_ex_Xgroup 21u
-#define khmer_syllable_machine_ex_Ygroup 22u
-#define khmer_syllable_machine_ex_ZWJ 6u
-#define khmer_syllable_machine_ex_ZWNJ 5u
-
-
-#line 60 "hb-ot-shape-complex-khmer-machine.hh"
-static const unsigned char _khmer_syllable_machine_trans_keys[] = {
- 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
- 5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
- 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
- 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
- 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
- 0
-};
-
-static const char _khmer_syllable_machine_key_spans[] = {
- 22, 17, 22, 17, 16, 17, 22, 17,
- 22, 17, 17, 22, 17, 16, 17, 22,
- 17, 22, 17, 22, 29, 25, 25, 25,
- 1, 18, 25, 25, 25, 16, 22, 25,
- 25, 1, 18, 25, 25, 16, 25, 25
-};
-
-static const short _khmer_syllable_machine_index_offsets[] = {
- 0, 23, 41, 64, 82, 99, 117, 140,
- 158, 181, 199, 217, 240, 258, 275, 293,
- 316, 334, 357, 375, 398, 428, 454, 480,
- 506, 508, 527, 553, 579, 605, 622, 645,
- 671, 697, 699, 718, 744, 770, 787, 813
-};
-
-static const char _khmer_syllable_machine_indicies[] = {
- 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 3, 0, 0, 0, 0, 4, 0, 1,
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 3,
- 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 3, 0, 0, 0, 0, 4, 0,
- 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 6, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 6, 0, 7, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 8, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 10, 0, 0,
- 0, 0, 4, 0, 9, 9, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 10, 0, 11, 11,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 12, 0,
- 0, 0, 0, 4, 0, 11, 11, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 0, 14,
- 14, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15,
- 13, 14, 14, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 15, 16, 16, 16, 16, 17, 16,
- 18, 18, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 16, 19, 19, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 19, 16, 20, 20, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 21, 16, 22, 22, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 23, 16, 16,
- 16, 16, 17, 16, 22, 22, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 23, 16, 24, 24,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 25, 16,
- 16, 16, 16, 17, 16, 24, 24, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 25, 16, 14,
- 14, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 26, 15,
- 16, 16, 16, 16, 17, 16, 28, 28,
- 27, 27, 29, 29, 27, 27, 27, 27,
- 2, 2, 27, 30, 27, 28, 27, 27,
- 27, 27, 15, 19, 27, 27, 27, 17,
- 23, 25, 21, 27, 32, 32, 31, 31,
- 31, 31, 31, 31, 31, 33, 31, 31,
- 31, 31, 31, 2, 3, 6, 31, 31,
- 31, 4, 10, 12, 8, 31, 34, 34,
- 31, 31, 31, 31, 31, 31, 31, 35,
- 31, 31, 31, 31, 31, 31, 3, 6,
- 31, 31, 31, 4, 10, 12, 8, 31,
- 5, 5, 31, 31, 31, 31, 31, 31,
- 31, 35, 31, 31, 31, 31, 31, 31,
- 4, 6, 31, 31, 31, 31, 31, 31,
- 8, 31, 6, 31, 7, 7, 31, 31,
- 31, 31, 31, 31, 31, 35, 31, 31,
- 31, 31, 31, 31, 8, 6, 31, 36,
- 36, 31, 31, 31, 31, 31, 31, 31,
- 35, 31, 31, 31, 31, 31, 31, 10,
- 6, 31, 31, 31, 4, 31, 31, 8,
- 31, 37, 37, 31, 31, 31, 31, 31,
- 31, 31, 35, 31, 31, 31, 31, 31,
- 31, 12, 6, 31, 31, 31, 4, 10,
- 31, 8, 31, 34, 34, 31, 31, 31,
- 31, 31, 31, 31, 33, 31, 31, 31,
- 31, 31, 31, 3, 6, 31, 31, 31,
- 4, 10, 12, 8, 31, 28, 28, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 28, 31, 14, 14,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 15, 38,
- 38, 38, 38, 17, 38, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 41, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 18,
- 18, 39, 39, 39, 39, 39, 39, 39,
- 41, 39, 39, 39, 39, 39, 39, 17,
- 19, 39, 39, 39, 39, 39, 39, 21,
- 39, 19, 39, 20, 20, 39, 39, 39,
- 39, 39, 39, 39, 41, 39, 39, 39,
- 39, 39, 39, 21, 19, 39, 42, 42,
- 39, 39, 39, 39, 39, 39, 39, 41,
- 39, 39, 39, 39, 39, 39, 23, 19,
- 39, 39, 39, 17, 39, 39, 21, 39,
- 43, 43, 39, 39, 39, 39, 39, 39,
- 39, 41, 39, 39, 39, 39, 39, 39,
- 25, 19, 39, 39, 39, 17, 23, 39,
- 21, 39, 44, 44, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 44, 39, 45, 45, 39, 39, 39,
- 39, 39, 39, 39, 30, 39, 39, 39,
- 39, 39, 26, 15, 19, 39, 39, 39,
- 17, 23, 25, 21, 39, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 30, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 0
-};
-
-static const char _khmer_syllable_machine_trans_targs[] = {
- 20, 1, 28, 22, 23, 3, 24, 5,
- 25, 7, 26, 9, 27, 20, 10, 31,
- 20, 32, 12, 33, 14, 34, 16, 35,
- 18, 36, 39, 20, 21, 30, 37, 20,
- 0, 29, 2, 4, 6, 8, 20, 20,
- 11, 13, 15, 17, 38, 19
-};
-
-static const char _khmer_syllable_machine_trans_actions[] = {
- 1, 0, 2, 2, 2, 0, 0, 0,
- 2, 0, 2, 0, 2, 3, 0, 4,
- 5, 2, 0, 0, 0, 2, 0, 2,
- 0, 2, 4, 8, 2, 9, 0, 10,
- 0, 0, 0, 0, 0, 0, 11, 12,
- 0, 0, 0, 0, 4, 0
-};
-
-static const char _khmer_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _khmer_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const unsigned char _khmer_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 39, 40,
- 40, 40, 40, 40, 40, 40, 40, 40
-};
-
-static const int khmer_syllable_machine_start = 20;
-static const int khmer_syllable_machine_first_final = 20;
-static const int khmer_syllable_machine_error = -1;
-
-static const int khmer_syllable_machine_en_main = 20;
-
-
-#line 43 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-
-#line 86 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_khmer (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
- {
- cs = khmer_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 106 "hb-ot-shape-complex-khmer-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 282 "hb-ot-shape-complex-khmer-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
- case 7:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 296 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
- _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
-
- _slen = _khmer_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
- ( info[p].khmer_category()) <= _keys[1] ?
- ( info[p].khmer_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _khmer_syllable_machine_trans_targs[_trans];
-
- if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 8:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 10:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 12:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_broken_cluster); }}
- break;
- case 11:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 1:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 5:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
- break;
- case 3:
-#line 1 "NONE"
- { switch( act ) {
- case 2:
- {{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
- break;
- case 3:
- {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
- break;
- }
- }
- break;
- case 4:
-#line 1 "NONE"
- {te = p+1;}
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 2;}
- break;
- case 9:
-#line 1 "NONE"
- {te = p+1;}
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 3;}
- break;
-#line 366 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
-_again:
- switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
- case 6:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 375 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 114 "hb-ot-shape-complex-khmer-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
deleted file mode 100644
index 35bfbb64d5..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum khmer_category_t
-{
- OT_Robatic = 20,
- OT_Xgroup = 21,
- OT_Ygroup = 22,
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
-};
-
-using khmer_position_t = indic_position_t;
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
- khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- *
- * These categories are experimentally extracted from what Uniscribe allows.
- */
- switch (u)
- {
- case 0x179Au:
- cat = (khmer_category_t) OT_Ra;
- break;
-
- case 0x17CCu:
- case 0x17C9u:
- case 0x17CAu:
- cat = OT_Robatic;
- break;
-
- case 0x17C6u:
- case 0x17CBu:
- case 0x17CDu:
- case 0x17CEu:
- case 0x17CFu:
- case 0x17D0u:
- case 0x17D1u:
- cat = OT_Xgroup;
- break;
-
- case 0x17C7u:
- case 0x17C8u:
- case 0x17DDu:
- case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
- cat = OT_Ygroup;
- break;
- }
-
- /*
- * Re-assign position.
- */
- if (cat == (khmer_category_t) OT_M)
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break;
- case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break;
- case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break;
- case POS_POST_C: cat = (khmer_category_t) OT_VPst; break;
- default: assert (0);
- }
-
- info.khmer_category() = cat;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
deleted file mode 100644
index f4ef33004d..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ /dev/null
@@ -1,492 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-
-#include "hb.hh"
-
-enum myanmar_syllable_type_t {
- myanmar_consonant_syllable,
- myanmar_punctuation_cluster,
- myanmar_broken_cluster,
- myanmar_non_myanmar_cluster,
-};
-
-
-#line 43 "hb-ot-shape-complex-myanmar-machine.hh"
-#define myanmar_syllable_machine_ex_A 10u
-#define myanmar_syllable_machine_ex_As 18u
-#define myanmar_syllable_machine_ex_C 1u
-#define myanmar_syllable_machine_ex_CS 19u
-#define myanmar_syllable_machine_ex_D 32u
-#define myanmar_syllable_machine_ex_D0 20u
-#define myanmar_syllable_machine_ex_DB 3u
-#define myanmar_syllable_machine_ex_GB 11u
-#define myanmar_syllable_machine_ex_H 4u
-#define myanmar_syllable_machine_ex_IV 2u
-#define myanmar_syllable_machine_ex_MH 21u
-#define myanmar_syllable_machine_ex_ML 33u
-#define myanmar_syllable_machine_ex_MR 22u
-#define myanmar_syllable_machine_ex_MW 23u
-#define myanmar_syllable_machine_ex_MY 24u
-#define myanmar_syllable_machine_ex_P 31u
-#define myanmar_syllable_machine_ex_PT 25u
-#define myanmar_syllable_machine_ex_Ra 16u
-#define myanmar_syllable_machine_ex_V 8u
-#define myanmar_syllable_machine_ex_VAbv 26u
-#define myanmar_syllable_machine_ex_VBlw 27u
-#define myanmar_syllable_machine_ex_VPre 28u
-#define myanmar_syllable_machine_ex_VPst 29u
-#define myanmar_syllable_machine_ex_VS 30u
-#define myanmar_syllable_machine_ex_ZWJ 6u
-#define myanmar_syllable_machine_ex_ZWNJ 5u
-
-
-#line 72 "hb-ot-shape-complex-myanmar-machine.hh"
-static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u,
- 0
-};
-
-static const char _myanmar_syllable_machine_key_spans[] = {
- 33, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 27, 27, 27, 28, 27, 31, 31, 31,
- 31, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 31, 27, 27, 27, 28, 27, 31, 31,
- 31, 31, 31, 31, 31, 33, 32, 1
-};
-
-static const short _myanmar_syllable_machine_index_offsets[] = {
- 0, 34, 66, 92, 97, 123, 147, 169,
- 191, 223, 251, 279, 307, 339, 356, 388,
- 420, 448, 476, 504, 533, 561, 593, 625,
- 657, 689, 721, 747, 752, 778, 802, 824,
- 846, 878, 906, 934, 962, 994, 1011, 1043,
- 1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280,
- 1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539
-};
-
-static const char _myanmar_syllable_machine_indicies[] = {
- 1, 1, 2, 3, 4, 4, 0, 5,
- 0, 6, 1, 0, 0, 0, 0, 7,
- 0, 8, 9, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 1,
- 21, 0, 23, 24, 25, 25, 22, 26,
- 22, 27, 22, 22, 22, 22, 22, 22,
- 22, 28, 22, 22, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 22, 22,
- 39, 22, 25, 25, 22, 26, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 40,
- 22, 22, 22, 22, 22, 22, 33, 22,
- 22, 22, 37, 22, 25, 25, 22, 26,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 41, 22, 25, 25, 22,
- 26, 22, 33, 22, 22, 22, 22, 22,
- 22, 22, 42, 22, 22, 22, 22, 22,
- 22, 33, 22, 25, 25, 22, 26, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 42, 22, 22, 22, 22, 22, 22, 33,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 43, 22,
- 22, 44, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 22, 22, 43, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 22,
- 22, 43, 22, 1, 1, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 1, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 28, 22, 22, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 46, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 22, 37, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 22, 35, 22, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 36, 37, 46, 22, 23, 22, 25,
- 25, 22, 26, 22, 27, 22, 22, 22,
- 22, 22, 22, 22, 46, 22, 22, 22,
- 22, 22, 22, 33, 34, 35, 36, 37,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 22, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 46, 22, 22, 29, 22, 22, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 47, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 24, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 28, 22, 22, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 49, 49, 48, 5, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 50, 48,
- 48, 48, 48, 48, 48, 14, 48, 48,
- 48, 18, 48, 49, 49, 48, 5, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 51, 48, 49, 49, 48, 5,
- 48, 14, 48, 48, 48, 48, 48, 48,
- 48, 52, 48, 48, 48, 48, 48, 48,
- 14, 48, 49, 49, 48, 5, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 52,
- 48, 48, 48, 48, 48, 48, 14, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 53, 48, 48,
- 54, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 48, 48, 53, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 48, 48,
- 53, 48, 56, 56, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 56, 48, 2, 3, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 57, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 48, 18, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 48, 16, 48, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 17, 18, 57, 48, 2, 48, 49, 49,
- 48, 5, 48, 6, 48, 48, 48, 48,
- 48, 48, 48, 57, 48, 48, 48, 48,
- 48, 48, 14, 15, 16, 17, 18, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 48, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 57,
- 48, 48, 10, 48, 48, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 58,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 3, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 8,
- 48, 48, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 23, 24, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 59,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 22, 22, 39, 22,
- 23, 60, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 28,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 22, 22, 22, 39, 22,
- 1, 1, 2, 3, 49, 49, 48, 5,
- 48, 6, 1, 48, 48, 48, 48, 1,
- 48, 8, 48, 48, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 48, 1,
- 21, 48, 1, 1, 61, 61, 61, 61,
- 61, 61, 61, 61, 1, 61, 61, 61,
- 61, 1, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 1, 61, 62, 61, 0
-};
-
-static const char _myanmar_syllable_machine_trans_targs[] = {
- 0, 1, 26, 37, 0, 27, 33, 51,
- 39, 54, 40, 46, 47, 48, 29, 42,
- 43, 44, 32, 50, 55, 45, 0, 2,
- 13, 0, 3, 9, 14, 15, 21, 22,
- 23, 5, 17, 18, 19, 8, 25, 20,
- 4, 6, 7, 10, 12, 11, 16, 24,
- 0, 0, 28, 30, 31, 34, 36, 35,
- 38, 41, 49, 52, 53, 0, 0
-};
-
-static const char _myanmar_syllable_machine_trans_actions[] = {
- 3, 0, 0, 0, 4, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 6, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 9, 10
-};
-
-static const char _myanmar_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _myanmar_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _myanmar_syllable_machine_eof_trans[] = {
- 0, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 23, 23, 49, 62, 62
-};
-
-static const int myanmar_syllable_machine_start = 0;
-static const int myanmar_syllable_machine_first_final = 0;
-static const int myanmar_syllable_machine_error = -1;
-
-static const int myanmar_syllable_machine_en_main = 0;
-
-
-#line 44 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_myanmar (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 382 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- cs = myanmar_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 398 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 412 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
- _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
-
- _slen = _myanmar_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
- ( info[p].myanmar_category()) <= _keys[1] ?
- ( info[p].myanmar_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _myanmar_syllable_machine_trans_targs[_trans];
-
- if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
- case 6:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 4:
-#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 10:
-#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
- break;
- case 8:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 3:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 5:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 7:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 9:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
-#line 462 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
-_again:
- switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 471 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-myanmar-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
deleted file mode 100644
index 7fbca3878f..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
- OT_As = 18, /* Asat */
- OT_D0 = 20, /* Digit zero */
- OT_DB = OT_N, /* Dot below */
- OT_GB = OT_PLACEHOLDER,
- OT_MH = 21, /* Various consonant medial types */
- OT_MR = 22, /* Various consonant medial types */
- OT_MW = 23, /* Various consonant medial types */
- OT_MY = 24, /* Various consonant medial types */
- OT_PT = 25, /* Pwo and other tones */
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
- OT_VS = 30, /* Variation selectors */
- OT_P = 31, /* Punctuation */
- OT_D = 32, /* Digits except zero */
- OT_ML = 33, /* Various consonant medial types */
-};
-
-using myanmar_position_t = indic_position_t;
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- unsigned int cat = type & 0xFFu;
- myanmar_position_t pos = (myanmar_position_t) (type >> 8);
-
- /* Myanmar
- * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
- */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
- cat = OT_VS;
-
- switch (u)
- {
- case 0x104Eu:
- cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
- break;
-
- case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
- case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
- case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
- case 0x25FEu:
- cat = OT_GB;
- break;
-
- case 0x1004u: case 0x101Bu: case 0x105Au:
- cat = OT_Ra;
- break;
-
- case 0x1032u: case 0x1036u:
- cat = OT_A;
- break;
-
- case 0x1039u:
- cat = OT_H;
- break;
-
- case 0x103Au:
- cat = OT_As;
- break;
-
- case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
- case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
- case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
- case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
- case 0x1097u: case 0x1098u: case 0x1099u:
- cat = OT_D;
- break;
-
- case 0x1040u:
- cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
- break;
-
- case 0x103Eu:
- cat = OT_MH;
- break;
-
- case 0x1060u:
- cat = OT_ML;
- break;
-
- case 0x103Cu:
- cat = OT_MR;
- break;
-
- case 0x103Du: case 0x1082u:
- cat = OT_MW;
- break;
-
- case 0x103Bu: case 0x105Eu: case 0x105Fu:
- cat = OT_MY;
- break;
-
- case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
- case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
- cat = OT_PT;
- break;
-
- case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
- case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
- case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
- cat = OT_SM;
- break;
-
- case 0x104Au: case 0x104Bu:
- cat = OT_P;
- break;
-
- case 0xAA74u: case 0xAA75u: case 0xAA76u:
- /* https://github.com/harfbuzz/harfbuzz/issues/218 */
- cat = OT_C;
- break;
- }
-
- if (cat == OT_M)
- {
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (myanmar_category_t) OT_VPre;
- pos = POS_PRE_M; break;
- case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break;
- case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break;
- case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break;
- }
- }
-
- info.myanmar_category() = cat;
- info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
deleted file mode 100644
index 468bd95c3f..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ /dev/null
@@ -1,849 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-use-machine.rl"
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-/* buffer var allocations */
-#define use_category() complex_var_u8_category()
-
-#define USE(Cat) use_syllable_machine_ex_##Cat
-
-enum use_syllable_type_t {
- use_virama_terminated_cluster,
- use_sakot_terminated_cluster,
- use_standard_cluster,
- use_number_joiner_terminated_cluster,
- use_numeral_cluster,
- use_symbol_cluster,
- use_hieroglyph_cluster,
- use_broken_cluster,
- use_non_cluster,
-};
-
-
-#line 57 "hb-ot-shape-complex-use-machine.hh"
-#define use_syllable_machine_ex_B 1u
-#define use_syllable_machine_ex_CGJ 6u
-#define use_syllable_machine_ex_CMAbv 31u
-#define use_syllable_machine_ex_CMBlw 32u
-#define use_syllable_machine_ex_CS 43u
-#define use_syllable_machine_ex_FAbv 24u
-#define use_syllable_machine_ex_FBlw 25u
-#define use_syllable_machine_ex_FMAbv 45u
-#define use_syllable_machine_ex_FMBlw 46u
-#define use_syllable_machine_ex_FMPst 47u
-#define use_syllable_machine_ex_FPst 26u
-#define use_syllable_machine_ex_G 49u
-#define use_syllable_machine_ex_GB 5u
-#define use_syllable_machine_ex_H 12u
-#define use_syllable_machine_ex_HN 13u
-#define use_syllable_machine_ex_IS 44u
-#define use_syllable_machine_ex_J 50u
-#define use_syllable_machine_ex_MAbv 27u
-#define use_syllable_machine_ex_MBlw 28u
-#define use_syllable_machine_ex_MPre 30u
-#define use_syllable_machine_ex_MPst 29u
-#define use_syllable_machine_ex_N 4u
-#define use_syllable_machine_ex_O 0u
-#define use_syllable_machine_ex_R 18u
-#define use_syllable_machine_ex_SB 51u
-#define use_syllable_machine_ex_SE 52u
-#define use_syllable_machine_ex_SMAbv 41u
-#define use_syllable_machine_ex_SMBlw 42u
-#define use_syllable_machine_ex_SUB 11u
-#define use_syllable_machine_ex_Sk 48u
-#define use_syllable_machine_ex_VAbv 33u
-#define use_syllable_machine_ex_VBlw 34u
-#define use_syllable_machine_ex_VMAbv 37u
-#define use_syllable_machine_ex_VMBlw 38u
-#define use_syllable_machine_ex_VMPre 23u
-#define use_syllable_machine_ex_VMPst 39u
-#define use_syllable_machine_ex_VPre 22u
-#define use_syllable_machine_ex_VPst 35u
-#define use_syllable_machine_ex_WJ 16u
-#define use_syllable_machine_ex_ZWNJ 14u
-
-
-#line 100 "hb-ot-shape-complex-use-machine.hh"
-static const unsigned char _use_syllable_machine_trans_keys[] = {
- 0u, 51u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
- 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u,
- 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u,
- 1u, 1u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 48u, 23u, 48u,
- 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 12u, 48u, 12u, 48u,
- 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u,
- 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
- 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 11u, 48u, 11u, 48u,
- 1u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
- 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 48u, 23u, 48u, 23u, 48u, 23u, 48u,
- 12u, 48u, 12u, 48u, 12u, 48u, 12u, 48u, 11u, 48u, 1u, 1u, 4u, 4u, 13u, 13u,
- 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
- 0
-};
-
-static const char _use_syllable_machine_key_spans[] = {
- 52, 38, 38, 48, 26, 24, 23, 22,
- 2, 1, 25, 25, 25, 1, 25, 27,
- 26, 26, 26, 37, 37, 37, 37, 38,
- 1, 38, 2, 1, 38, 38, 48, 26,
- 24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 27, 26, 26, 26, 37, 37,
- 37, 37, 38, 1, 1, 1, 38, 38,
- 48, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 1, 25, 27, 26, 26, 26,
- 37, 37, 37, 37, 38, 1, 38, 38,
- 48, 26, 24, 23, 22, 2, 1, 25,
- 25, 25, 1, 25, 27, 26, 26, 26,
- 37, 37, 37, 37, 38, 1, 1, 1,
- 48, 38, 2, 1, 5, 3, 4, 3
-};
-
-static const short _use_syllable_machine_index_offsets[] = {
- 0, 53, 92, 131, 180, 207, 232, 256,
- 279, 282, 284, 310, 336, 362, 364, 390,
- 418, 445, 472, 499, 537, 575, 613, 651,
- 690, 692, 731, 734, 736, 775, 814, 863,
- 890, 915, 939, 962, 965, 967, 993, 1019,
- 1045, 1047, 1073, 1101, 1128, 1155, 1182, 1220,
- 1258, 1296, 1334, 1373, 1375, 1377, 1379, 1418,
- 1457, 1506, 1533, 1558, 1582, 1605, 1608, 1610,
- 1636, 1662, 1688, 1690, 1716, 1744, 1771, 1798,
- 1825, 1863, 1901, 1939, 1977, 2016, 2018, 2057,
- 2096, 2145, 2172, 2197, 2221, 2244, 2247, 2249,
- 2275, 2301, 2327, 2329, 2355, 2383, 2410, 2437,
- 2464, 2502, 2540, 2578, 2616, 2655, 2657, 2659,
- 2661, 2710, 2749, 2752, 2754, 2760, 2764, 2769
-};
-
-static const char _use_syllable_machine_indicies[] = {
- 0, 1, 2, 2, 3, 4, 2, 2,
- 2, 2, 2, 5, 6, 7, 2, 2,
- 2, 2, 8, 2, 2, 2, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 2, 23, 24, 25,
- 2, 26, 27, 28, 29, 30, 31, 32,
- 29, 33, 2, 34, 2, 36, 37, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 35, 52,
- 53, 54, 35, 55, 56, 35, 57, 58,
- 59, 60, 57, 35, 36, 37, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 48, 48, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 57, 58, 59,
- 60, 57, 35, 36, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 39, 40, 41, 42, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 52,
- 53, 54, 35, 35, 35, 35, 35, 58,
- 59, 60, 61, 35, 39, 40, 41, 42,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 52, 53, 54, 35, 35, 35,
- 35, 35, 58, 59, 60, 61, 35, 40,
- 41, 42, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 58, 59, 60, 35,
- 41, 42, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 58, 59, 60, 35,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 58, 59, 60, 35, 58,
- 59, 35, 59, 35, 40, 41, 42, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 52, 53, 54, 35, 35, 35, 35,
- 35, 58, 59, 60, 61, 35, 40, 41,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 53, 54, 35, 35,
- 35, 35, 35, 58, 59, 60, 61, 35,
- 40, 41, 42, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 54,
- 35, 35, 35, 35, 35, 58, 59, 60,
- 61, 35, 62, 35, 40, 41, 42, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 58, 59, 60, 61, 35, 38, 39,
- 40, 41, 42, 35, 35, 35, 35, 35,
- 35, 49, 50, 51, 35, 52, 53, 54,
- 35, 35, 35, 35, 35, 58, 59, 60,
- 61, 35, 39, 40, 41, 42, 35, 35,
- 35, 35, 35, 35, 49, 50, 51, 35,
- 52, 53, 54, 35, 35, 35, 35, 35,
- 58, 59, 60, 61, 35, 39, 40, 41,
- 42, 35, 35, 35, 35, 35, 35, 35,
- 50, 51, 35, 52, 53, 54, 35, 35,
- 35, 35, 35, 58, 59, 60, 61, 35,
- 39, 40, 41, 42, 35, 35, 35, 35,
- 35, 35, 35, 35, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 35, 58, 59,
- 60, 61, 35, 39, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 38, 39, 40,
- 41, 42, 35, 44, 45, 35, 35, 35,
- 49, 50, 51, 35, 52, 53, 54, 35,
- 35, 35, 35, 35, 58, 59, 60, 61,
- 35, 39, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 38, 39, 40, 41, 42,
- 35, 35, 45, 35, 35, 35, 49, 50,
- 51, 35, 52, 53, 54, 35, 35, 35,
- 35, 35, 58, 59, 60, 61, 35, 39,
- 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 38, 39, 40, 41, 42, 35, 35,
- 35, 35, 35, 35, 49, 50, 51, 35,
- 52, 53, 54, 35, 35, 35, 35, 35,
- 58, 59, 60, 61, 35, 39, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 35,
- 35, 35, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 35, 58, 59,
- 60, 61, 35, 36, 37, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 35,
- 48, 49, 50, 51, 35, 52, 53, 54,
- 35, 35, 35, 35, 57, 58, 59, 60,
- 57, 35, 36, 35, 36, 37, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 35, 52, 53,
- 54, 35, 35, 35, 35, 57, 58, 59,
- 60, 57, 35, 55, 56, 35, 56, 35,
- 64, 65, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 1, 75, 76, 77,
- 78, 63, 79, 80, 81, 63, 63, 63,
- 63, 82, 83, 84, 85, 86, 63, 64,
- 65, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 75, 76, 77, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 82, 83, 84, 85, 86, 63, 64, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 67, 68, 69, 70,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 79, 80, 81, 63, 63, 63,
- 63, 63, 83, 84, 85, 87, 63, 67,
- 68, 69, 70, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 79, 80, 81,
- 63, 63, 63, 63, 63, 83, 84, 85,
- 87, 63, 68, 69, 70, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 83,
- 84, 85, 63, 69, 70, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 83,
- 84, 85, 63, 70, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 83, 84,
- 85, 63, 83, 84, 63, 84, 63, 68,
- 69, 70, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 79, 80, 81, 63,
- 63, 63, 63, 63, 83, 84, 85, 87,
- 63, 68, 69, 70, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 80,
- 81, 63, 63, 63, 63, 63, 83, 84,
- 85, 87, 63, 68, 69, 70, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 81, 63, 63, 63, 63, 63,
- 83, 84, 85, 87, 63, 89, 88, 68,
- 69, 70, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 83, 84, 85, 87,
- 63, 66, 67, 68, 69, 70, 63, 63,
- 63, 63, 63, 63, 76, 77, 78, 63,
- 79, 80, 81, 63, 63, 63, 63, 63,
- 83, 84, 85, 87, 63, 67, 68, 69,
- 70, 63, 63, 63, 63, 63, 63, 76,
- 77, 78, 63, 79, 80, 81, 63, 63,
- 63, 63, 63, 83, 84, 85, 87, 63,
- 67, 68, 69, 70, 63, 63, 63, 63,
- 63, 63, 63, 77, 78, 63, 79, 80,
- 81, 63, 63, 63, 63, 63, 83, 84,
- 85, 87, 63, 67, 68, 69, 70, 63,
- 63, 63, 63, 63, 63, 63, 63, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 63, 83, 84, 85, 87, 63, 67, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 66, 67, 68, 69, 70, 63, 72, 73,
- 63, 63, 63, 76, 77, 78, 63, 79,
- 80, 81, 63, 63, 63, 63, 63, 83,
- 84, 85, 87, 63, 67, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 66, 67,
- 68, 69, 70, 63, 63, 73, 63, 63,
- 63, 76, 77, 78, 63, 79, 80, 81,
- 63, 63, 63, 63, 63, 83, 84, 85,
- 87, 63, 67, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 66, 67, 68, 69,
- 70, 63, 63, 63, 63, 63, 63, 76,
- 77, 78, 63, 79, 80, 81, 63, 63,
- 63, 63, 63, 83, 84, 85, 87, 63,
- 67, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 66, 67, 68, 69, 70, 71,
- 72, 73, 63, 63, 63, 76, 77, 78,
- 63, 79, 80, 81, 63, 63, 63, 63,
- 63, 83, 84, 85, 87, 63, 64, 65,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 63, 75, 76, 77, 78, 63,
- 79, 80, 81, 63, 63, 63, 63, 82,
- 83, 84, 85, 86, 63, 64, 90, 92,
- 91, 3, 93, 94, 95, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105,
- 106, 107, 108, 109, 63, 110, 111, 112,
- 63, 55, 56, 63, 113, 114, 115, 85,
- 116, 63, 94, 95, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 106, 106,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 113, 114, 115, 85, 116,
- 63, 94, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 97,
- 98, 99, 100, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 110, 111, 112,
- 63, 63, 63, 63, 63, 114, 115, 85,
- 117, 63, 97, 98, 99, 100, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 110, 111, 112, 63, 63, 63, 63, 63,
- 114, 115, 85, 117, 63, 98, 99, 100,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 114, 115, 85, 63, 99, 100,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 114, 115, 85, 63, 100, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 114, 115, 85, 63, 114, 115, 63,
- 115, 63, 98, 99, 100, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 110,
- 111, 112, 63, 63, 63, 63, 63, 114,
- 115, 85, 117, 63, 98, 99, 100, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 111, 112, 63, 63, 63, 63,
- 63, 114, 115, 85, 117, 63, 98, 99,
- 100, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 112, 63, 63,
- 63, 63, 63, 114, 115, 85, 117, 63,
- 118, 88, 98, 99, 100, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 114,
- 115, 85, 117, 63, 96, 97, 98, 99,
- 100, 63, 63, 63, 63, 63, 63, 107,
- 108, 109, 63, 110, 111, 112, 63, 63,
- 63, 63, 63, 114, 115, 85, 117, 63,
- 97, 98, 99, 100, 63, 63, 63, 63,
- 63, 63, 107, 108, 109, 63, 110, 111,
- 112, 63, 63, 63, 63, 63, 114, 115,
- 85, 117, 63, 97, 98, 99, 100, 63,
- 63, 63, 63, 63, 63, 63, 108, 109,
- 63, 110, 111, 112, 63, 63, 63, 63,
- 63, 114, 115, 85, 117, 63, 97, 98,
- 99, 100, 63, 63, 63, 63, 63, 63,
- 63, 63, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 63, 114, 115, 85, 117,
- 63, 97, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 96, 97, 98, 99, 100,
- 63, 102, 103, 63, 63, 63, 107, 108,
- 109, 63, 110, 111, 112, 63, 63, 63,
- 63, 63, 114, 115, 85, 117, 63, 97,
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 96, 97, 98, 99, 100, 63, 63,
- 103, 63, 63, 63, 107, 108, 109, 63,
- 110, 111, 112, 63, 63, 63, 63, 63,
- 114, 115, 85, 117, 63, 97, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 96,
- 97, 98, 99, 100, 63, 63, 63, 63,
- 63, 63, 107, 108, 109, 63, 110, 111,
- 112, 63, 63, 63, 63, 63, 114, 115,
- 85, 117, 63, 97, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 63, 63, 63,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 63, 114, 115, 85, 117,
- 63, 94, 95, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 96, 97, 98, 99,
- 100, 101, 102, 103, 104, 63, 106, 107,
- 108, 109, 63, 110, 111, 112, 63, 63,
- 63, 63, 113, 114, 115, 85, 116, 63,
- 94, 90, 94, 95, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 96, 97, 98,
- 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 63, 110, 111, 112, 63,
- 63, 63, 63, 113, 114, 115, 85, 116,
- 63, 5, 6, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 19, 19, 20,
- 21, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 29, 30, 31, 32, 29, 119,
- 5, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 10, 11,
- 12, 13, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 23, 24, 25, 119,
- 119, 119, 119, 119, 30, 31, 32, 120,
- 119, 10, 11, 12, 13, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 23,
- 24, 25, 119, 119, 119, 119, 119, 30,
- 31, 32, 120, 119, 11, 12, 13, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 30, 31, 32, 119, 12, 13, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 30, 31, 32, 119, 13, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 30, 31, 32, 119, 30, 31, 119, 31,
- 119, 11, 12, 13, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 23, 24,
- 25, 119, 119, 119, 119, 119, 30, 31,
- 32, 120, 119, 11, 12, 13, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 24, 25, 119, 119, 119, 119, 119,
- 30, 31, 32, 120, 119, 11, 12, 13,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 25, 119, 119, 119,
- 119, 119, 30, 31, 32, 120, 119, 121,
- 119, 11, 12, 13, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 30, 31,
- 32, 120, 119, 9, 10, 11, 12, 13,
- 119, 119, 119, 119, 119, 119, 20, 21,
- 22, 119, 23, 24, 25, 119, 119, 119,
- 119, 119, 30, 31, 32, 120, 119, 10,
- 11, 12, 13, 119, 119, 119, 119, 119,
- 119, 20, 21, 22, 119, 23, 24, 25,
- 119, 119, 119, 119, 119, 30, 31, 32,
- 120, 119, 10, 11, 12, 13, 119, 119,
- 119, 119, 119, 119, 119, 21, 22, 119,
- 23, 24, 25, 119, 119, 119, 119, 119,
- 30, 31, 32, 120, 119, 10, 11, 12,
- 13, 119, 119, 119, 119, 119, 119, 119,
- 119, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 119, 30, 31, 32, 120, 119,
- 10, 119, 119, 119, 119, 119, 119, 119,
- 119, 119, 9, 10, 11, 12, 13, 119,
- 15, 16, 119, 119, 119, 20, 21, 22,
- 119, 23, 24, 25, 119, 119, 119, 119,
- 119, 30, 31, 32, 120, 119, 10, 119,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 9, 10, 11, 12, 13, 119, 119, 16,
- 119, 119, 119, 20, 21, 22, 119, 23,
- 24, 25, 119, 119, 119, 119, 119, 30,
- 31, 32, 120, 119, 10, 119, 119, 119,
- 119, 119, 119, 119, 119, 119, 9, 10,
- 11, 12, 13, 119, 119, 119, 119, 119,
- 119, 20, 21, 22, 119, 23, 24, 25,
- 119, 119, 119, 119, 119, 30, 31, 32,
- 120, 119, 10, 119, 119, 119, 119, 119,
- 119, 119, 119, 119, 9, 10, 11, 12,
- 13, 14, 15, 16, 119, 119, 119, 20,
- 21, 22, 119, 23, 24, 25, 119, 119,
- 119, 119, 119, 30, 31, 32, 120, 119,
- 5, 6, 119, 119, 119, 119, 119, 119,
- 119, 119, 119, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 119, 19, 20, 21,
- 22, 119, 23, 24, 25, 119, 119, 119,
- 119, 29, 30, 31, 32, 29, 119, 5,
- 119, 122, 119, 7, 119, 1, 119, 119,
- 119, 1, 119, 119, 119, 119, 119, 5,
- 6, 7, 119, 119, 119, 119, 119, 119,
- 119, 119, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22,
- 119, 23, 24, 25, 119, 26, 27, 119,
- 29, 30, 31, 32, 29, 119, 5, 6,
- 119, 119, 119, 119, 119, 119, 119, 119,
- 119, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 119,
- 23, 24, 25, 119, 119, 119, 119, 29,
- 30, 31, 32, 29, 119, 26, 27, 119,
- 27, 119, 1, 123, 123, 123, 1, 123,
- 125, 124, 33, 124, 33, 125, 124, 125,
- 124, 33, 124, 34, 124, 0
-};
-
-static const char _use_syllable_machine_trans_targs[] = {
- 1, 28, 0, 52, 54, 79, 80, 102,
- 104, 92, 81, 82, 83, 84, 96, 97,
- 98, 99, 105, 100, 93, 94, 95, 87,
- 88, 89, 106, 107, 108, 101, 85, 86,
- 0, 109, 111, 0, 2, 3, 15, 4,
- 5, 6, 7, 19, 20, 21, 22, 25,
- 23, 16, 17, 18, 10, 11, 12, 26,
- 27, 24, 8, 9, 0, 13, 14, 0,
- 29, 30, 42, 31, 32, 33, 34, 46,
- 47, 48, 49, 50, 43, 44, 45, 37,
- 38, 39, 51, 35, 36, 0, 51, 40,
- 0, 41, 0, 0, 53, 0, 55, 56,
- 68, 57, 58, 59, 60, 72, 73, 74,
- 75, 78, 76, 69, 70, 71, 63, 64,
- 65, 77, 61, 62, 77, 66, 67, 0,
- 90, 91, 103, 0, 0, 110
-};
-
-static const char _use_syllable_machine_trans_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 0, 5, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 7,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 8, 0, 0, 9, 10, 0,
- 11, 0, 12, 13, 0, 14, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 8, 0, 0, 10, 0, 0, 15,
- 0, 0, 0, 16, 17, 0
-};
-
-static const char _use_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _use_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _use_syllable_machine_eof_trans[] = {
- 0, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 89, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 91, 92, 94, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 89, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 91, 64, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 124, 125, 125, 125
-};
-
-static const int use_syllable_machine_start = 0;
-static const int use_syllable_machine_first_final = 0;
-static const int use_syllable_machine_error = -1;
-
-static const int use_syllable_machine_en_main = 0;
-
-
-#line 58 "hb-ot-shape-complex-use-machine.rl"
-
-
-
-#line 181 "hb-ot-shape-complex-use-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
- for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-
-template <typename Iter>
-struct machine_index_t :
- hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t>
-{
- machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t> (),
- it (o.it), is_null (o.is_null) {}
-
- static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
- static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-
- typename Iter::item_t __item__ () const { return *it; }
- typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
- unsigned __len__ () const { return it.len (); }
- void __next__ () { ++it; }
- void __forward__ (unsigned n) { it += n; }
- void __prev__ () { --it; }
- void __rewind__ (unsigned n) { it -= n; }
-
- void operator = (unsigned n)
- {
- assert (n == 0);
- is_null = true;
- }
- explicit operator bool () { return !is_null; }
-
- void operator = (const machine_index_t& o)
- {
- is_null = o.is_null;
- unsigned index = (*it).first;
- unsigned n = (*o.it).first;
- if (index < n) it += n - index; else if (index > n) it -= index - n;
- }
- bool operator == (const machine_index_t& o) const
- { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
- bool operator != (const machine_index_t& o) const { return !(*this == o); }
-
- private:
- Iter it;
- bool is_null = false;
-};
-struct
-{
- template <typename Iter,
- hb_requires (hb_is_iterable (Iter))>
- machine_index_t<hb_iter_type<Iter>>
- operator () (Iter&& it) const
- { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
-}
-HB_FUNCOBJ (machine_index);
-
-
-
-static bool
-not_ccs_default_ignorable (const hb_glyph_info_t &i)
-{ return i.use_category() != USE(CGJ); }
-
-static inline void
-find_syllables_use (hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- auto p =
- + hb_iter (info, buffer->len)
- | hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
- hb_second)
- | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
- {
- if (p.second.use_category() == USE(ZWNJ))
- for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_ccs_default_ignorable (info[i]))
- return !_hb_glyph_info_is_unicode_mark (&info[i]);
- return true;
- })
- | hb_enumerate
- | machine_index
- ;
- auto pe = p + p.len ();
- auto eof = +pe;
- auto ts = +p;
- auto te = +p;
- unsigned int act HB_UNUSED;
- int cs;
-
-#line 702 "hb-ot-shape-complex-use-machine.hh"
- {
- cs = use_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 281 "hb-ot-shape-complex-use-machine.rl"
-
-
- unsigned int syllable_serial = 1;
-
-#line 715 "hb-ot-shape-complex-use-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 729 "hb-ot-shape-complex-use-machine.hh"
- }
-
- _keys = _use_syllable_machine_trans_keys + (cs<<1);
- _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
-
- _slen = _use_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
- ( (*p).second.second.use_category()) <= _keys[1] ?
- ( (*p).second.second.use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _use_syllable_machine_trans_targs[_trans];
-
- if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 9:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_standard_cluster); }}
- break;
- case 6:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_symbol_cluster); }}
- break;
- case 4:
-#line 176 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_broken_cluster); }}
- break;
- case 3:
-#line 177 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_non_cluster); }}
- break;
- case 11:
-#line 170 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
- break;
- case 7:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_standard_cluster); }}
- break;
- case 14:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
- break;
- case 13:
-#line 173 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_numeral_cluster); }}
- break;
- case 5:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_symbol_cluster); }}
- break;
- case 17:
-#line 175 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
- break;
- case 15:
-#line 176 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_broken_cluster); }}
- break;
- case 16:
-#line 177 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_non_cluster); }}
- break;
- case 12:
-#line 1 "NONE"
- { switch( act ) {
- case 1:
- {{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
- break;
- case 2:
- {{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
- break;
- }
- }
- break;
- case 8:
-#line 1 "NONE"
- {te = p+1;}
-#line 169 "hb-ot-shape-complex-use-machine.rl"
- {act = 1;}
- break;
- case 10:
-#line 1 "NONE"
- {te = p+1;}
-#line 170 "hb-ot-shape-complex-use-machine.rl"
- {act = 2;}
- break;
-#line 819 "hb-ot-shape-complex-use-machine.hh"
- }
-
-_again:
- switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 828 "hb-ot-shape-complex-use-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _use_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 286 "hb-ot-shape-complex-use-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
index aa5a8eeaa3..7db0b25b73 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -29,7 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-normalize.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape.hh"
@@ -69,7 +69,7 @@
* - When a font does not support a character but supports its canonical
* decomposition, well, use the decomposition.
*
- * - The complex shapers can customize the compose and decompose functions to
+ * - The shapers can customize the compose and decompose functions to
* offload some of their requirements to the normalizer. For example, the
* Indic shaper may want to disallow recomposing of two matras.
*/
@@ -143,8 +143,7 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
return 1;
}
- unsigned int ret;
- if ((ret = decompose (c, shortest, a))) {
+ if (unsigned ret = decompose (c, shortest, a)) {
if (b) {
output_char (buffer, b, b_glyph);
return ret + 1;
@@ -223,7 +222,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
unsigned int end,
bool short_circuit HB_UNUSED)
{
- /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
+ /* Currently if there's a variation-selector we give-up on normalization, it's just too hard. */
hb_buffer_t * const buffer = c->buffer;
hb_font_t * const font = c->font;
for (; buffer->idx < end - 1 && buffer->successful;) {
@@ -395,7 +394,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
break;
/* We are going to do a O(n^2). Only do this if the sequence is short. */
- if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+ if (end - i > HB_OT_SHAPE_MAX_COMBINING_MARKS) {
i = end;
continue;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc
index 99aadab3f0..0806abb7dd 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc
@@ -37,7 +37,7 @@
#include "hb-shaper-impl.hh"
#include "hb-ot-shape.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape-fallback.hh"
#include "hb-ot-shape-normalize.hh"
@@ -86,14 +86,14 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
, apply_morx (_hb_apply_morx (face, props))
#endif
{
- shaper = hb_ot_shape_complex_categorize (this);
+ shaper = hb_ot_shaper_categorize (this);
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
/* https://github.com/harfbuzz/harfbuzz/issues/1528 */
- if (apply_morx && shaper != &_hb_ot_complex_shaper_default)
- shaper = &_hb_ot_complex_shaper_dumber;
+ if (apply_morx && shaper != &_hb_ot_shaper_default)
+ shaper = &_hb_ot_shaper_dumber;
}
void
@@ -927,7 +927,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
+hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
@@ -946,7 +946,7 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
- hb_ot_substitute_complex (c);
+ hb_ot_substitute_plan (c);
#ifndef HB_NO_AAT_SHAPE
if (c->plan->apply_morx && c->plan->apply_gpos)
@@ -1039,7 +1039,7 @@ hb_ot_position_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_position_complex (const hb_ot_shape_context_t *c)
+hb_ot_position_plan (const hb_ot_shape_context_t *c)
{
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
@@ -1124,7 +1124,7 @@ hb_ot_position (const hb_ot_shape_context_t *c)
hb_ot_position_default (c);
- hb_ot_position_complex (c);
+ hb_ot_position_plan (c);
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
hb_buffer_reverse (c->buffer);
@@ -1159,8 +1159,6 @@ hb_propagate_flags (hb_buffer_t *buffer)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- c->buffer->enter ();
-
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.hh b/thirdparty/harfbuzz/src/hb-ot-shape.hh
index e8c81015c7..17fa58b337 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh
@@ -61,7 +61,7 @@ struct hb_shape_plan_key_t;
struct hb_ot_shape_plan_t
{
hb_segment_properties_t props;
- const struct hb_ot_complex_shaper_t *shaper;
+ const struct hb_ot_shaper_t *shaper;
hb_ot_map_t map;
hb_aat_map_t aat_map;
const void *data;
@@ -158,7 +158,7 @@ struct hb_ot_shape_planner_t
#endif
bool script_zero_marks : 1;
bool script_fallback_mark_positioning : 1;
- const struct hb_ot_complex_shaper_t *shaper;
+ const struct hb_ot_shaper_t *shaper;
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,
const hb_segment_properties_t *props);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh
index 78f46c1cac..b9f92f72d6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh
@@ -24,8 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
+#ifndef HB_OT_SHAPER_ARABIC_FALLBACK_HH
+#define HB_OT_SHAPER_ARABIC_FALLBACK_HH
#include "hb.hh"
@@ -34,7 +34,11 @@
/* Features ordered the same as the entries in shaping_table rows,
- * followed by rlig. Don't change. */
+ * followed by rlig. Don't change.
+ *
+ * We currently support one subtable per lookup, and one lookup
+ * per feature. But we allow duplicate features, so we use that!
+ */
static const hb_tag_t arabic_fallback_features[] =
{
HB_TAG('i','n','i','t'),
@@ -42,6 +46,8 @@ static const hb_tag_t arabic_fallback_features[] =
HB_TAG('f','i','n','a'),
HB_TAG('i','s','o','l'),
HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
};
static OT::SubstLookup *
@@ -95,20 +101,25 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS
return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
}
+template <typename T>
static OT::SubstLookup *
arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font)
+ hb_font_t *font,
+ const T &ligature_table,
+ unsigned lookup_flags)
{
OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
unsigned int num_first_glyphs = 0;
- /* We know that all our ligatures are 2-component */
+ /* We know that all our ligatures have the same number of components. */
OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
- OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
+ OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) *
+ ARRAY_LENGTH_CONST (ligature_table[0].ligatures[0].components)];
unsigned int num_ligatures = 0;
+ unsigned int num_components = 0;
/* Populate arrays */
@@ -133,21 +144,32 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
{
unsigned int first_glyph_idx = first_glyphs_indirection[i];
- for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
+ for (unsigned int ligature_idx = 0; ligature_idx < ARRAY_LENGTH (ligature_table[0].ligatures); ligature_idx++)
{
- hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second;
- hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature;
- hb_codepoint_t second_glyph, ligature_glyph;
- if (!second_u ||
- !hb_font_get_glyph (font, second_u, 0, &second_glyph) ||
- !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
+ hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].ligature;
+ hb_codepoint_t ligature_glyph;
+ if (!hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
continue;
- ligature_per_first_glyph_count_list[i]++;
+ const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components;
+ unsigned component_count = ARRAY_LENGTH_CONST (components);
+
+ for (unsigned i = 0; i < component_count; i++)
+ {
+ hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[i];
+ hb_codepoint_t component_glyph;
+ if (!component_u ||
+ !hb_font_get_glyph (font, component_u, 0, &component_glyph))
+ continue;
+ component_list[num_components++] = component_glyph;
+ }
+
+ component_count_list[num_ligatures] = 1 + component_count;
ligature_list[num_ligatures] = ligature_glyph;
- component_count_list[num_ligatures] = 2;
- component_list[num_ligatures] = second_glyph;
+
+ ligature_per_first_glyph_count_list[i]++;
+
num_ligatures++;
}
}
@@ -161,14 +183,13 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN
hb_serialize_context_t c (buf, sizeof (buf));
OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
bool ret = lookup->serialize_ligature (&c,
- OT::LookupFlag::IgnoreMarks,
+ lookup_flags,
hb_sorted_array (first_glyphs, num_first_glyphs),
hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
hb_array (ligature_list, num_ligatures),
hb_array (component_count_list, num_ligatures),
- hb_array (component_list, num_ligatures));
+ hb_array (component_list, num_components));
c.end_serialize ();
- /* TODO sanitize the results? */
return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
}
@@ -181,10 +202,18 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
if (feature_index < 4)
return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
else
- return arabic_fallback_synthesize_lookup_ligature (plan, font);
+ {
+ switch (feature_index) {
+ case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_3_table, OT::LookupFlag::IgnoreMarks);
+ case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks);
+ case 6: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0);
+ }
+ }
+ assert (false);
+ return nullptr;
}
-#define ARABIC_FALLBACK_MAX_LOOKUPS 5
+#define ARABIC_FALLBACK_MAX_LOOKUPS ARRAY_LENGTH_CONST (arabic_fallback_features)
struct arabic_fallback_plan_t
{
@@ -201,7 +230,7 @@ struct arabic_fallback_plan_t
#endif
#ifdef HB_WITH_WIN1256
-#include "hb-ot-shape-complex-arabic-win1256.hh"
+#include "hb-ot-shaper-arabic-win1256.hh"
#endif
struct ManifestLookup
@@ -230,9 +259,8 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS
return false;
const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
- static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) ==
+ static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) <=
ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), "");
- /* TODO sanitize the table? */
unsigned j = 0;
unsigned int count = manifest.len;
@@ -264,7 +292,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
const hb_ot_shape_plan_t *plan,
hb_font_t *font)
{
- static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
+ static_assert ((ARRAY_LENGTH_CONST (arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
unsigned int j = 0;
for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
{
@@ -345,4 +373,4 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
}
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH */
+#endif /* HB_OT_SHAPER_ARABIC_FALLBACK_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh
index e6339ee72b..a5ce3a6c93 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh
@@ -12,8 +12,8 @@
* # Date: 2021-07-10, 00:35:31 GMT
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
+#ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
+#define HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
static bool
has_arabic_joining (hb_script_t script)
@@ -42,6 +42,6 @@ has_arabic_joining (hb_script_t script)
}
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH */
+#endif /* HB_OT_SHAPER_ARABIC_JOINING_LIST_HH */
/* == End of generated function == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh
new file mode 100644
index 0000000000..ba86772f84
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh
@@ -0,0 +1,118 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-arabic-pua.py
+ *
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_PUA_HH
+#define HB_OT_SHAPER_ARABIC_PUA_HH
+
+static const uint8_t
+_hb_arabic_u8[464] =
+{
+ 84, 86, 85, 85, 85, 85, 85,213, 16, 34, 34, 34, 34, 34, 35, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 36, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 82, 16, 0, 0, 0, 0, 1, 2, 3, 4,
+ 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 7,
+ 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 0, 22, 0, 23, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 16, 34, 34, 34, 35, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 66, 16, 50, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68,101, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,152,186, 76, 77, 68,254, 16, 50,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 5, 6,
+ 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 23, 23, 29, 30, 31, 32, 33, 0, 0, 0, 0,
+ 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 40,
+ 41, 42, 0, 43, 44, 0, 0, 45, 46, 0, 47, 48, 49, 0, 0, 0,
+ 0, 50, 0, 0, 51, 52, 0, 53, 54, 55, 56, 57, 58, 0, 0, 0,
+ 0, 0, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 66,
+ 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+};
+static const uint16_t
+_hb_arabic_u16[720] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,61728,61729,61730, 0, 0,61733, 0, 0,
+ 61736,61737,61738,61739,61790,61741,61742,61743,61872,61873,61874,61875,61876,61877,61878,61879,
+ 61880,61881,61754,61755, 0,61757, 0,61759, 0, 0, 0,61787,61788,61789, 0, 0,
+ 0, 0, 0,61731, 0, 0, 0, 0, 0, 0, 0,61732, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,61734, 0, 0, 0, 0, 0, 0, 0,61735,
+ 0, 0, 0, 0,61740, 0, 0, 0, 0, 0, 0,61755, 0, 0, 0,61759,
+ 0,61869,61765,61763,61883,61767,61882,61761,61770,61865,61772,61774,61777,61780,61783,61784,
+ 61785,61786,61792,61794,61796,61798,61800,61801,61802,61806,61810,61696,61696,61696,61696,61696,
+ 61791,61813,61816,61818,61820,61822,61921,61860,61861,61868,61864,61895,61896,61899,61892,61893,
+ 61898,61897,61894,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696, 0,
+ 61744,61745,61746,61747,61748,61749,61750,61751,61752,61753, 0,61790,61790, 0, 0, 0,
+ 0, 0, 0, 0,61708,61709,61710,61711,61756,61758, 0, 0, 0, 0, 0, 0,
+ 0,61765,61766,61763,61764,61883,61883,61767,61768,61882,61871,61870,61870,61761,61762,61770,
+ 61770,61769,61769,61865,61866,61772,61772,61771,61771,61774,61774,61773,61773,61777,61776,61775,
+ 61775,61780,61779,61778,61778,61783,61782,61781,61781,61784,61784,61785,61785,61786,61786,61792,
+ 61792,61794,61794,61793,61793,61796,61796,61795,61795,61798,61798,61797,61797,61800,61800,61799,
+ 61799,61801,61801,61801,61801,61802,61802,61802,61802,61806,61805,61803,61804,61810,61809,61807,
+ 61808,61813,61813,61811,61812,61816,61816,61814,61815,61818,61818,61817,61817,61820,61820,61819,
+ 61819,61822,61822,61821,61821,61921,61921,61823,61823,61860,61859,61857,61858,61861,61861,61868,
+ 61867,61864,61863,61862,61862,61888,61889,61886,61887,61890,61891,61885,61884, 0, 0, 0,
+ 0, 0, 0, 0,61984,61985,61986, 0, 0,61989, 0, 0,61992,61993,61994,61995,
+ 62046,61997,61998,61999, 0, 0,62010,62011, 0,62013, 0,62015, 0, 0, 0,62043,
+ 0,62045, 0, 0, 0, 0, 0,61987, 0, 0, 0,61988, 0, 0, 0,61990,
+ 0, 0, 0,61991,61996, 0, 0, 0, 0, 0, 0,62011, 0, 0, 0,62015,
+ 0,62165,62021,62019,62170,62023,62169,62017,62028,62161,62032,62036,62040,62048,62052,62053,
+ 62055,62057,62059,62064,62068,62072,62078,62114,62115,62122,62126,61952,61952,61952,61952,61952,
+ 62047,62130,62134,62138,62142,62146,62150,62154,62155,62164,62160,62183,62184,62187,62180,62181,
+ 62186,62185,62182,61952,61952,61952,61952, 0,62000,62001,62002,62003,62004,62005,62006,62007,
+ 62008,62009, 0,62046,62046, 0, 0, 0,61964,61965,61966,61967,62012,62014, 0, 0,
+ 61954, 0,61981, 0, 0, 0,61955, 0,61982, 0,61956, 0, 0, 0,62111, 0,
+ 0, 0, 0,61970,61971,61972,61957, 0,61980, 0, 0, 0, 0, 0,61958, 0,
+ 61983, 0, 0, 0, 0, 0,62191, 0,62188,62189,62192, 0, 0, 0,61973, 0,
+ 0,62098, 0, 0,61974, 0, 0,62099, 0, 0,62101, 0, 0,61975, 0, 0,
+ 62100, 0, 0, 0,62080,62081,62082,62102, 0,62083,62084,62085,62103, 0, 0, 0,
+ 62106, 0,62107, 0,62108, 0, 0, 0,61976, 0, 0, 0, 0,62086,62087,62088,
+ 62109,61978,62089,62090,62091,62110,62093,62094, 0,62104, 0, 0, 0, 0,62095,62096,
+ 62097,62105, 0, 0,61977, 0, 0, 0, 0, 0,62075,62077,61968, 0, 0, 0,
+ 0,62021,62022,62019,62020,62170,62171,62023,62024,62169,62168,62166,62167,62017,62018,62028,
+ 62027,62025,62026,62161,62162,62032,62031,62029,62030,62036,62035,62033,62034,62040,62039,62037,
+ 62038,62048,62044,62041,62042,62052,62051,62049,62050,62053,62054,62055,62056,62057,62058,62059,
+ 62060,62064,62063,62061,62062,62068,62067,62065,62066,62072,62071,62069,62070,62078,62076,62073,
+ 62074,62114,62113,62079,62193,62118,62117,62115,62116,62122,62121,62119,62120,62126,62125,62123,
+ 62124,62130,62129,62127,62128,62134,62133,62131,62132,62138,62137,62135,62136,62142,62141,62139,
+ 62140,62146,62145,62143,62144,62150,62149,62147,62148,62154,62153,62151,62152,62155,62156,62164,
+ 62163,62160,62159,62157,62158,62176,62177,62174,62175,62178,62179,62172,62173, 0, 0, 0,
+};
+
+static inline unsigned
+_hb_arabic_b2 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>2]>>((i&3u)<<1))&3u;
+}
+static inline unsigned
+_hb_arabic_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_simp_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[((_hb_arabic_u8[40+(((_hb_arabic_b4(8+_hb_arabic_u8,((_hb_arabic_b2(_hb_arabic_u8,u>>3>>4>>4))<<4)+((u>>3>>4)&15u)))<<4)+((u>>3)&15u))])<<3)+((u)&7u)]:0;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_trad_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[320+(((_hb_arabic_u8[208+(((_hb_arabic_b4(168+_hb_arabic_u8,((_hb_arabic_b4(136+_hb_arabic_u8,u>>2>>4>>4))<<4)+((u>>2>>4)&15u)))<<4)+((u>>2)&15u))])<<2)+((u)&3u))]:0;
+}
+
+#endif /* HB_OT_SHAPER_ARABIC_PUA_HH */
+
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh
index c158964f2c..fd3d8645d1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh
@@ -13,8 +13,8 @@
* UnicodeData.txt does not have a header.
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
+#ifndef HB_OT_SHAPER_ARABIC_TABLE_HH
+#define HB_OT_SHAPER_ARABIC_TABLE_HH
#define A JOINING_GROUP_ALAPH
@@ -416,26 +416,141 @@ static const uint16_t shaping_table[][4] =
static const struct ligature_set_t {
uint16_t first;
struct ligature_pairs_t {
- uint16_t second;
+ uint16_t components[1];
uint16_t ligature;
- } ligatures[4];
+ } ligatures[14];
} ligature_table[] =
{
+ { 0xFE91u, {
+ { {0xFEE2u}, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE92u, {
+ { {0xFEAEu}, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE97u, {
+ { {0xFEE2u}, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE98u, {
+ { {0xFEAEu}, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE9Bu, {
+ { {0xFEE2u}, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */
+ }},
+ { 0xFE9Fu, {
+ { {0xFEE4u}, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA3u, {
+ { {0xFEE4u}, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA7u, {
+ { {0xFEE4u}, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB3u, {
+ { {0xFEE4u}, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB7u, {
+ { {0xFEE4u}, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFED3u, {
+ { {0xFEF2u}, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */
+ }},
{ 0xFEDFu, {
- { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
- { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
- { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
- { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+ { {0xFE9Eu}, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */
+ { {0xFEA0u}, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */
+ { {0xFEA2u}, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */
+ { {0xFEA4u}, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */
+ { {0xFEA6u}, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */
+ { {0xFEA8u}, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */
+ { {0xFEE2u}, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */
+ { {0xFEF2u}, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */
+ { {0xFEECu}, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */
+ { {0xFE82u}, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+ { {0xFE84u}, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+ { {0xFE88u}, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+ { {0xFE8Eu}, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
}},
{ 0xFEE0u, {
- { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
- { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
- { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
- { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ { {0xFEF0u}, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */
+ { {0xFE82u}, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+ { {0xFE84u}, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+ { {0xFE88u}, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+ { {0xFE8Eu}, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ }},
+ { 0xFEE3u, {
+ { {0xFEA0u}, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEE7u, {
+ { {0xFEE2u}, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */
+ }},
+ { 0xFEE8u, {
+ { {0xFEF2u}, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */
+ }},
+ { 0xFEF3u, {
+ { {0xFEA0u}, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEF4u, {
+ { {0xFEAEu}, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */
+ }},
+};
+
+
+static const struct ligature_mark_set_t {
+ uint16_t first;
+ struct ligature_pairs_t {
+ uint16_t components[1];
+ uint16_t ligature;
+ } ligatures[5];
+} ligature_mark_table[] =
+{
+ { 0x0651u, {
+ { {0x064Cu}, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */
+ { {0x064Eu}, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */
+ { {0x064Fu}, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */
+ { {0x0650u}, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */
+ { {0x064Bu}, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */
+ }},
+};
+
+
+static const struct ligature_3_set_t {
+ uint16_t first;
+ struct ligature_triplets_t {
+ uint16_t components[2];
+ uint16_t ligature;
+ } ligatures[3];
+} ligature_3_table[] =
+{
+ { 0xFEDFu, {
+ { {0xFEE4u, 0xFEA4u}, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */
+ { {0xFEE0u, 0xFEEAu}, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */
+ { {0xFEE4u, 0xFEA0u}, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */
}},
};
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
+#endif /* HB_OT_SHAPER_ARABIC_TABLE_HH */
/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh
index 429974d05b..b8d481c813 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh
@@ -24,7 +24,7 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
+#ifndef HB_OT_SHAPER_ARABIC_WIN1256_HH
/*
@@ -342,8 +342,8 @@ OT_TABLE_END
#include "hb.hh" /* Make check-includes.sh happy. */
#endif
#ifdef OT_MEASURE
-#include "hb-ot-shape-complex-arabic-win1256.hh"
+#include "hb-ot-shaper-arabic-win1256.hh"
#endif
-#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
+#define HB_OT_SHAPER_ARABIC_WIN1256_HH
+#endif /* HB_OT_SHAPER_ARABIC_WIN1256_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
index 224f8b842e..e869d78509 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
@@ -28,14 +28,14 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shaper-arabic.hh"
#include "hb-ot-shape.hh"
/* buffer var allocations */
-#define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */
+#define arabic_shaping_action() ot_shaper_var_u8_auxiliary() /* arabic shaping action */
-#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
+#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_SHAPER0
/* See:
* https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
@@ -81,7 +81,7 @@ enum hb_arabic_joining_type_t {
JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */
};
-#include "hb-ot-shape-complex-arabic-table.hh"
+#include "hb-ot-shaper-arabic-table.hh"
static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
{
@@ -172,6 +172,14 @@ record_stch (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer);
static void
+deallocate_buffer_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+}
+
+static void
collect_features_arabic (hb_ot_shape_planner_t *plan)
{
hb_ot_map_builder_t *map = &plan->map;
@@ -213,6 +221,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
map->add_gsub_pause (nullptr);
}
+ map->add_gsub_pause (deallocate_buffer_var);
/* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script
* however, it says a ZWJ should also mean "don't ligate". So we run
@@ -240,7 +249,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
map->enable_feature (HB_TAG('m','s','e','t'));
}
-#include "hb-ot-shape-complex-arabic-fallback.hh"
+#include "hb-ot-shaper-arabic-fallback.hh"
struct arabic_shape_plan_t
{
@@ -405,7 +414,7 @@ arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
+#ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK
return;
#endif
@@ -619,8 +628,6 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
hb_font_t *font)
{
apply_stch (plan, buffer, font);
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
}
/* https://www.unicode.org/reports/tr53/ */
@@ -689,7 +696,7 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
/* Shift it! */
DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d", cc, i, j);
- hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS];
+ hb_glyph_info_t temp[HB_OT_SHAPE_MAX_COMBINING_MARKS];
assert (j - i <= ARRAY_LENGTH (temp));
buffer->merge_clusters (start, j);
memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
@@ -720,7 +727,7 @@ reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
}
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
+const hb_ot_shaper_t _hb_ot_shaper_arabic =
{
collect_features_arabic,
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh
index 5bf6ff6338..a025b1a399 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh
@@ -26,12 +26,12 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
+#ifndef HB_OT_SHAPER_ARABIC_HH
+#define HB_OT_SHAPER_ARABIC_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
struct arabic_shape_plan_t;
@@ -47,4 +47,4 @@ setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
hb_buffer_t *buffer,
hb_script_t script);
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
+#endif /* HB_OT_SHAPER_ARABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
index a755aea098..25716aa81f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
@@ -28,10 +28,10 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
+const hb_ot_shaper_t _hb_ot_shaper_default =
{
nullptr, /* collect_features */
nullptr, /* override_features */
@@ -51,7 +51,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
/* Same as default but no mark advance zeroing / fallback positioning.
* Dumbest shaper ever, basically. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
+const hb_ot_shaper_t _hb_ot_shaper_dumber =
{
nullptr, /* collect_features */
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc
index 3bc9e9b961..aa507c75ca 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
/* Hangul shaper */
@@ -119,7 +119,7 @@ data_destroy_hangul (void *data)
#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
/* buffer var allocations */
-#define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */
+#define hangul_shaping_feature() ot_shaper_var_u8_auxiliary() /* hangul jamo shaping feature */
static bool
is_zero_width_char (hb_font_t *font,
@@ -414,7 +414,7 @@ setup_masks_hangul (const hb_ot_shape_plan_t *plan,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
+const hb_ot_shaper_t _hb_ot_shaper_hangul =
{
collect_features_hangul,
override_features_hangul,
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc
index 334d3ded82..f3b6cde179 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
static bool
@@ -74,7 +74,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
bool found = (bool) c->unicode->compose (a, b, ab);
-#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
+#ifdef HB_NO_OT_SHAPER_HEBREW_FALLBACK
return found;
#endif
@@ -163,7 +163,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
+const hb_ot_shaper_t _hb_ot_shaper_hebrew =
{
nullptr, /* collect_features */
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
new file mode 100644
index 0000000000..d52b13f616
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
@@ -0,0 +1,589 @@
+
+#line 1 "hb-ot-shaper-indic-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_INDIC_MACHINE_HH
+#define HB_OT_SHAPER_INDIC_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define indic_category() ot_shaper_var_u8_category() /* indic_category_t */
+#define indic_position() ot_shaper_var_u8_auxiliary() /* indic_position_t */
+
+using indic_category_t = unsigned;
+using indic_position_t = ot_position_t;
+
+#define I_Cat(Cat) indic_syllable_machine_ex_##Cat
+
+enum indic_syllable_type_t {
+ indic_consonant_syllable,
+ indic_vowel_syllable,
+ indic_standalone_cluster,
+ indic_symbol_cluster,
+ indic_broken_cluster,
+ indic_non_indic_cluster,
+};
+
+
+#line 57 "hb-ot-shaper-indic-machine.hh"
+#define indic_syllable_machine_ex_A 9u
+#define indic_syllable_machine_ex_C 1u
+#define indic_syllable_machine_ex_CM 16u
+#define indic_syllable_machine_ex_CS 18u
+#define indic_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define indic_syllable_machine_ex_H 4u
+#define indic_syllable_machine_ex_M 7u
+#define indic_syllable_machine_ex_N 3u
+#define indic_syllable_machine_ex_PLACEHOLDER 10u
+#define indic_syllable_machine_ex_RS 12u
+#define indic_syllable_machine_ex_Ra 15u
+#define indic_syllable_machine_ex_Repha 14u
+#define indic_syllable_machine_ex_SM 8u
+#define indic_syllable_machine_ex_Symbol 17u
+#define indic_syllable_machine_ex_V 2u
+#define indic_syllable_machine_ex_VD 9u
+#define indic_syllable_machine_ex_X 0u
+#define indic_syllable_machine_ex_ZWJ 6u
+#define indic_syllable_machine_ex_ZWNJ 5u
+
+
+#line 79 "hb-ot-shaper-indic-machine.hh"
+static const unsigned char _indic_syllable_machine_trans_keys[] = {
+ 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 8u, 8u, 8u,
+ 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 12u, 4u, 12u, 8u, 8u, 5u, 7u,
+ 5u, 8u, 4u, 8u, 4u, 8u, 4u, 12u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u,
+ 4u, 8u, 5u, 8u, 8u, 8u, 1u, 18u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u,
+ 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 1u, 15u, 3u, 9u,
+ 4u, 9u, 5u, 9u, 4u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u,
+ 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u,
+ 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u,
+ 4u, 9u, 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 8u,
+ 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u,
+ 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u,
+ 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 12u, 4u, 8u, 3u, 16u,
+ 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 12u, 5u, 9u,
+ 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 0
+};
+
+static const char _indic_syllable_machine_key_spans[] = {
+ 1, 5, 3, 4, 5, 9, 5, 1,
+ 3, 4, 5, 9, 9, 9, 1, 3,
+ 4, 5, 5, 9, 1, 3, 4, 5,
+ 5, 4, 1, 18, 14, 14, 13, 15,
+ 5, 5, 1, 5, 15, 15, 15, 7,
+ 6, 5, 6, 5, 7, 5, 14, 14,
+ 14, 14, 13, 15, 14, 14, 13, 15,
+ 5, 1, 5, 15, 15, 7, 6, 5,
+ 6, 5, 5, 7, 5, 14, 14, 5,
+ 14, 14, 13, 15, 14, 15, 5, 1,
+ 5, 15, 15, 7, 6, 5, 14, 6,
+ 5, 5, 7, 5, 14, 9, 5, 14,
+ 14, 13, 15, 14, 15, 5, 1, 5,
+ 15, 15, 7, 6, 5, 14, 6, 5,
+ 5, 7, 5, 16, 14, 16, 9, 5,
+ 1, 5, 15, 7, 5, 5, 1, 5,
+ 15
+};
+
+static const short _indic_syllable_machine_index_offsets[] = {
+ 0, 2, 8, 12, 17, 23, 33, 39,
+ 41, 45, 50, 56, 66, 76, 86, 88,
+ 92, 97, 103, 109, 119, 121, 125, 130,
+ 136, 142, 147, 149, 168, 183, 198, 212,
+ 228, 234, 240, 242, 248, 264, 280, 296,
+ 304, 311, 317, 324, 330, 338, 344, 359,
+ 374, 389, 404, 418, 434, 449, 464, 478,
+ 494, 500, 502, 508, 524, 540, 548, 555,
+ 561, 568, 574, 580, 588, 594, 609, 624,
+ 630, 645, 660, 674, 690, 705, 721, 727,
+ 729, 735, 751, 767, 775, 782, 788, 803,
+ 810, 816, 822, 830, 836, 851, 861, 867,
+ 882, 897, 911, 927, 942, 958, 964, 966,
+ 972, 988, 1004, 1012, 1019, 1025, 1040, 1047,
+ 1053, 1059, 1067, 1073, 1090, 1105, 1122, 1132,
+ 1138, 1140, 1146, 1162, 1170, 1176, 1182, 1184,
+ 1190
+};
+
+static const unsigned char _indic_syllable_machine_indicies[] = {
+ 1, 0, 2, 3, 3, 4, 1, 0,
+ 3, 3, 4, 0, 3, 3, 4, 1,
+ 0, 5, 3, 3, 4, 1, 0, 2,
+ 3, 3, 4, 1, 0, 0, 0, 6,
+ 0, 8, 9, 9, 10, 11, 7, 11,
+ 7, 9, 9, 10, 7, 9, 9, 10,
+ 11, 7, 12, 9, 9, 10, 11, 7,
+ 8, 9, 9, 10, 11, 7, 7, 7,
+ 13, 7, 8, 9, 9, 10, 11, 7,
+ 7, 7, 14, 7, 16, 17, 17, 18,
+ 19, 15, 15, 15, 20, 15, 19, 15,
+ 17, 17, 18, 21, 17, 17, 18, 19,
+ 15, 16, 17, 17, 18, 19, 15, 22,
+ 17, 17, 18, 19, 15, 24, 25, 25,
+ 26, 27, 23, 23, 23, 28, 23, 27,
+ 23, 25, 25, 26, 23, 25, 25, 26,
+ 27, 23, 24, 25, 25, 26, 27, 23,
+ 29, 25, 25, 26, 27, 23, 17, 17,
+ 18, 1, 0, 31, 30, 33, 34, 35,
+ 36, 37, 38, 18, 19, 39, 40, 40,
+ 20, 32, 41, 42, 43, 44, 45, 32,
+ 47, 48, 49, 50, 4, 1, 51, 46,
+ 46, 6, 46, 46, 46, 52, 46, 53,
+ 48, 54, 54, 4, 1, 51, 46, 46,
+ 46, 46, 46, 46, 52, 46, 48, 54,
+ 54, 4, 1, 51, 46, 46, 46, 46,
+ 46, 46, 52, 46, 33, 46, 46, 46,
+ 55, 56, 46, 1, 51, 46, 46, 46,
+ 46, 46, 33, 46, 57, 57, 46, 1,
+ 51, 46, 51, 46, 46, 58, 51, 46,
+ 51, 46, 51, 46, 46, 46, 51, 46,
+ 33, 46, 59, 46, 57, 57, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 33, 46, 46, 46, 57, 57, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 33, 46, 46, 46, 57, 56, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 60, 61, 62, 62, 4, 1, 51, 46,
+ 61, 62, 62, 4, 1, 51, 46, 62,
+ 62, 4, 1, 51, 46, 63, 64, 64,
+ 4, 1, 51, 46, 55, 65, 46, 1,
+ 51, 46, 55, 46, 57, 57, 46, 1,
+ 51, 46, 57, 65, 46, 1, 51, 46,
+ 47, 48, 54, 54, 4, 1, 51, 46,
+ 46, 46, 46, 46, 46, 52, 46, 47,
+ 48, 49, 54, 4, 1, 51, 46, 46,
+ 6, 46, 46, 46, 52, 46, 67, 68,
+ 69, 70, 10, 11, 71, 66, 66, 14,
+ 66, 66, 66, 72, 66, 73, 68, 74,
+ 70, 10, 11, 71, 66, 66, 66, 66,
+ 66, 66, 72, 66, 68, 74, 70, 10,
+ 11, 71, 66, 66, 66, 66, 66, 66,
+ 72, 66, 75, 66, 66, 66, 76, 77,
+ 66, 11, 71, 66, 66, 66, 66, 66,
+ 75, 66, 78, 68, 79, 80, 10, 11,
+ 71, 66, 66, 13, 66, 66, 66, 72,
+ 66, 81, 68, 74, 74, 10, 11, 71,
+ 66, 66, 66, 66, 66, 66, 72, 66,
+ 68, 74, 74, 10, 11, 71, 66, 66,
+ 66, 66, 66, 66, 72, 66, 75, 66,
+ 66, 66, 82, 77, 66, 11, 71, 66,
+ 66, 66, 66, 66, 75, 66, 71, 66,
+ 66, 83, 71, 66, 71, 66, 71, 66,
+ 66, 66, 71, 66, 75, 66, 84, 66,
+ 82, 82, 66, 11, 71, 66, 66, 66,
+ 66, 66, 75, 66, 75, 66, 66, 66,
+ 82, 82, 66, 11, 71, 66, 66, 66,
+ 66, 66, 75, 66, 85, 86, 87, 87,
+ 10, 11, 71, 66, 86, 87, 87, 10,
+ 11, 71, 66, 87, 87, 10, 11, 71,
+ 66, 88, 89, 89, 10, 11, 71, 66,
+ 76, 90, 66, 11, 71, 66, 82, 82,
+ 66, 11, 71, 66, 76, 66, 82, 82,
+ 66, 11, 71, 66, 82, 90, 66, 11,
+ 71, 66, 78, 68, 74, 74, 10, 11,
+ 71, 66, 66, 66, 66, 66, 66, 72,
+ 66, 78, 68, 79, 74, 10, 11, 71,
+ 66, 66, 13, 66, 66, 66, 72, 66,
+ 8, 9, 9, 10, 11, 66, 67, 68,
+ 74, 70, 10, 11, 71, 66, 66, 66,
+ 66, 66, 66, 72, 66, 92, 36, 93,
+ 93, 18, 19, 39, 91, 91, 91, 91,
+ 91, 91, 43, 91, 36, 93, 93, 18,
+ 19, 39, 91, 91, 91, 91, 91, 91,
+ 43, 91, 94, 91, 91, 91, 95, 96,
+ 91, 19, 39, 91, 91, 91, 91, 91,
+ 94, 91, 35, 36, 97, 98, 18, 19,
+ 39, 91, 91, 20, 91, 91, 91, 43,
+ 91, 94, 91, 91, 91, 99, 96, 91,
+ 19, 39, 91, 91, 91, 91, 91, 94,
+ 91, 39, 91, 91, 100, 39, 91, 39,
+ 91, 39, 91, 91, 91, 39, 91, 94,
+ 91, 101, 91, 99, 99, 91, 19, 39,
+ 91, 91, 91, 91, 91, 94, 91, 94,
+ 91, 91, 91, 99, 99, 91, 19, 39,
+ 91, 91, 91, 91, 91, 94, 91, 102,
+ 103, 104, 104, 18, 19, 39, 91, 103,
+ 104, 104, 18, 19, 39, 91, 104, 104,
+ 18, 19, 39, 91, 35, 36, 93, 93,
+ 18, 19, 39, 91, 91, 91, 91, 91,
+ 91, 43, 91, 105, 106, 106, 18, 19,
+ 39, 91, 95, 107, 91, 19, 39, 91,
+ 99, 99, 91, 19, 39, 91, 95, 91,
+ 99, 99, 91, 19, 39, 91, 99, 107,
+ 91, 19, 39, 91, 35, 36, 97, 93,
+ 18, 19, 39, 91, 91, 20, 91, 91,
+ 91, 43, 91, 16, 17, 17, 18, 19,
+ 108, 108, 108, 20, 108, 16, 17, 17,
+ 18, 19, 108, 110, 111, 112, 113, 26,
+ 27, 114, 109, 109, 28, 109, 109, 109,
+ 115, 109, 116, 111, 113, 113, 26, 27,
+ 114, 109, 109, 109, 109, 109, 109, 115,
+ 109, 111, 113, 113, 26, 27, 114, 109,
+ 109, 109, 109, 109, 109, 115, 109, 117,
+ 109, 109, 109, 118, 119, 109, 27, 114,
+ 109, 109, 109, 109, 109, 117, 109, 110,
+ 111, 112, 40, 26, 27, 114, 109, 109,
+ 28, 109, 109, 109, 115, 109, 117, 109,
+ 109, 109, 120, 119, 109, 27, 114, 109,
+ 109, 109, 109, 109, 117, 109, 114, 109,
+ 109, 121, 114, 109, 114, 109, 114, 109,
+ 109, 109, 114, 109, 117, 109, 122, 109,
+ 120, 120, 109, 27, 114, 109, 109, 109,
+ 109, 109, 117, 109, 117, 109, 109, 109,
+ 120, 120, 109, 27, 114, 109, 109, 109,
+ 109, 109, 117, 109, 123, 124, 125, 125,
+ 26, 27, 114, 109, 124, 125, 125, 26,
+ 27, 114, 109, 125, 125, 26, 27, 114,
+ 109, 110, 111, 113, 113, 26, 27, 114,
+ 109, 109, 109, 109, 109, 109, 115, 109,
+ 126, 127, 127, 26, 27, 114, 109, 118,
+ 128, 109, 27, 114, 109, 120, 120, 109,
+ 27, 114, 109, 118, 109, 120, 120, 109,
+ 27, 114, 109, 120, 128, 109, 27, 114,
+ 109, 33, 34, 35, 36, 97, 93, 18,
+ 19, 39, 40, 40, 20, 91, 91, 33,
+ 43, 91, 47, 129, 49, 50, 4, 1,
+ 51, 46, 46, 6, 46, 46, 46, 52,
+ 46, 33, 34, 35, 36, 130, 131, 18,
+ 132, 133, 46, 40, 20, 46, 46, 33,
+ 43, 46, 16, 134, 134, 18, 132, 51,
+ 46, 46, 20, 46, 133, 46, 46, 135,
+ 133, 46, 133, 46, 133, 46, 46, 46,
+ 133, 46, 33, 46, 59, 16, 134, 134,
+ 18, 132, 51, 46, 46, 46, 46, 46,
+ 33, 46, 137, 136, 138, 138, 136, 31,
+ 139, 136, 138, 138, 136, 31, 139, 136,
+ 139, 136, 136, 140, 139, 136, 139, 136,
+ 139, 136, 136, 136, 139, 136, 33, 108,
+ 108, 108, 108, 108, 108, 108, 108, 40,
+ 108, 108, 108, 108, 33, 108, 0
+};
+
+static const unsigned char _indic_syllable_machine_trans_targs[] = {
+ 27, 33, 38, 2, 39, 45, 46, 27,
+ 55, 8, 61, 56, 68, 69, 72, 27,
+ 77, 15, 83, 78, 86, 27, 91, 27,
+ 100, 21, 106, 101, 109, 114, 27, 125,
+ 27, 28, 48, 73, 75, 93, 94, 79,
+ 95, 115, 116, 87, 123, 128, 27, 29,
+ 31, 5, 47, 34, 42, 30, 1, 32,
+ 36, 0, 35, 37, 40, 41, 3, 43,
+ 4, 44, 27, 49, 51, 12, 71, 57,
+ 64, 50, 6, 52, 66, 59, 53, 11,
+ 70, 54, 7, 58, 60, 62, 63, 9,
+ 65, 10, 67, 27, 74, 17, 76, 89,
+ 81, 13, 92, 14, 80, 82, 84, 85,
+ 16, 88, 18, 90, 27, 27, 96, 98,
+ 19, 23, 102, 110, 97, 99, 112, 104,
+ 20, 103, 105, 107, 108, 22, 111, 24,
+ 113, 117, 118, 122, 119, 120, 25, 121,
+ 27, 124, 26, 126, 127
+};
+
+static const char _indic_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 0, 2, 2, 2, 3,
+ 2, 0, 2, 0, 2, 2, 2, 4,
+ 2, 0, 5, 0, 5, 6, 2, 7,
+ 2, 0, 2, 0, 2, 2, 8, 0,
+ 11, 2, 2, 5, 0, 12, 12, 0,
+ 2, 5, 2, 5, 2, 0, 13, 2,
+ 0, 0, 2, 0, 2, 2, 0, 2,
+ 2, 0, 0, 2, 2, 2, 0, 0,
+ 0, 2, 14, 2, 0, 0, 2, 0,
+ 2, 2, 0, 2, 2, 2, 2, 0,
+ 2, 2, 0, 0, 2, 2, 2, 0,
+ 0, 0, 2, 15, 5, 0, 5, 2,
+ 2, 0, 5, 0, 0, 2, 5, 5,
+ 0, 0, 0, 2, 16, 17, 2, 0,
+ 0, 0, 0, 2, 2, 2, 2, 2,
+ 0, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 18, 18, 0, 0, 0, 0,
+ 19, 2, 0, 0, 0
+};
+
+static const char _indic_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const char _indic_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const short _indic_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 8, 8,
+ 8, 8, 8, 8, 8, 16, 16, 22,
+ 16, 16, 16, 24, 24, 24, 24, 24,
+ 24, 1, 31, 0, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 109, 109, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 92, 47, 47, 47, 47,
+ 47, 47, 47, 137, 137, 137, 137, 137,
+ 109
+};
+
+static const int indic_syllable_machine_start = 27;
+static const int indic_syllable_machine_first_final = 27;
+static const int indic_syllable_machine_error = -1;
+
+static const int indic_syllable_machine_en_main = 27;
+
+
+#line 58 "hb-ot-shaper-indic-machine.rl"
+
+
+
+#line 117 "hb-ot-shaper-indic-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_indic (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 426 "hb-ot-shaper-indic-machine.hh"
+ {
+ cs = indic_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 137 "hb-ot-shaper-indic-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 442 "hb-ot-shaper-indic-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _indic_syllable_machine_from_state_actions[cs] ) {
+ case 10:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 456 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ _keys = _indic_syllable_machine_trans_keys + (cs<<1);
+ _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
+
+ _slen = _indic_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
+ ( info[p].indic_category()) <= _keys[1] ?
+ ( info[p].indic_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _indic_syllable_machine_trans_targs[_trans];
+
+ if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _indic_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 11:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 13:
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 14:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 17:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 19:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 15:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 16:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 1:
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 3:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 7:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 8:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 4:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 6:
+#line 1 "NONE"
+ { switch( act ) {
+ case 1:
+ {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
+ break;
+ case 5:
+ {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 6:
+ {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
+ break;
+ }
+ }
+ break;
+ case 18:
+#line 1 "NONE"
+ {te = p+1;}
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {act = 1;}
+ break;
+ case 5:
+#line 1 "NONE"
+ {te = p+1;}
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {act = 5;}
+ break;
+ case 12:
+#line 1 "NONE"
+ {te = p+1;}
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {act = 6;}
+ break;
+#line 559 "hb-ot-shaper-indic-machine.hh"
+ }
+
+_again:
+ switch ( _indic_syllable_machine_to_state_actions[cs] ) {
+ case 9:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 568 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _indic_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 145 "hb-ot-shaper-indic-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_INDIC_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
new file mode 100644
index 0000000000..8994f3ca59
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
@@ -0,0 +1,560 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # IndicPositionalCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-indic.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-myanmar-machine.hh"
+
+/* indic */
+#define OT_X I_Cat(X)
+#define OT_C I_Cat(C)
+#define OT_V I_Cat(V)
+#define OT_N I_Cat(N)
+#define OT_H I_Cat(H)
+#define OT_ZWNJ I_Cat(ZWNJ)
+#define OT_ZWJ I_Cat(ZWJ)
+#define OT_M I_Cat(M)
+#define OT_SM I_Cat(SM)
+#define OT_A I_Cat(A)
+#define OT_VD I_Cat(VD)
+#define OT_PLACEHOLDER I_Cat(PLACEHOLDER)
+#define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE)
+#define OT_RS I_Cat(RS)
+#define OT_Repha I_Cat(Repha)
+#define OT_Ra I_Cat(Ra)
+#define OT_CM I_Cat(CM)
+#define OT_Symbol I_Cat(Symbol)
+#define OT_CS I_Cat(CS)
+/* khmer */
+#define OT_VAbv K_Cat(VAbv)
+#define OT_VBlw K_Cat(VBlw)
+#define OT_VPre K_Cat(VPre)
+#define OT_VPst K_Cat(VPst)
+#define OT_Robatic K_Cat(Robatic)
+#define OT_Xgroup K_Cat(Xgroup)
+#define OT_Ygroup K_Cat(Ygroup)
+/* myanmar */
+static_assert (OT_VAbv == M_Cat(VAbv), "");
+static_assert (OT_VBlw == M_Cat(VBlw), "");
+static_assert (OT_VPre == M_Cat(VPre), "");
+static_assert (OT_VPst == M_Cat(VPst), "");
+#define OT_IV M_Cat(IV)
+#define OT_As M_Cat(As)
+#define OT_DB M_Cat(DB)
+#define OT_GB M_Cat(GB)
+#define OT_MH M_Cat(MH)
+#define OT_MR M_Cat(MR)
+#define OT_MW M_Cat(MW)
+#define OT_MY M_Cat(MY)
+#define OT_PT M_Cat(PT)
+#define OT_VS M_Cat(VS)
+#define OT_ML M_Cat(ML)
+
+
+#define _OT_A OT_A /* 53 chars; A */
+#define _OT_As OT_As /* 1 chars; As */
+#define _OT_C OT_C /* 478 chars; C */
+#define _OT_CM OT_CM /* 1 chars; CM */
+#define _OT_CS OT_CS /* 2 chars; CS */
+#define _OT_DC OT_DOTTEDCIRCLE /* 1 chars; DOTTEDCIRCLE */
+#define _OT_H OT_H /* 11 chars; H */
+#define _OT_M OT_M /* 143 chars; M */
+#define _OT_MH OT_MH /* 1 chars; MH */
+#define _OT_ML OT_ML /* 1 chars; ML */
+#define _OT_MR OT_MR /* 1 chars; MR */
+#define _OT_MW OT_MW /* 2 chars; MW */
+#define _OT_MY OT_MY /* 3 chars; MY */
+#define _OT_N OT_N /* 17 chars; N */
+#define _OT_GB OT_PLACEHOLDER /* 165 chars; PLACEHOLDER */
+#define _OT_PT OT_PT /* 8 chars; PT */
+#define _OT_R OT_Ra /* 14 chars; Ra */
+#define _OT_Rf OT_Repha /* 1 chars; Repha */
+#define _OT_Rt OT_Robatic /* 3 chars; Robatic */
+#define _OT_SM OT_SM /* 55 chars; SM */
+#define _OT_S OT_Symbol /* 22 chars; Symbol */
+#define _OT_V OT_V /* 172 chars; V */
+#define _OT_VA OT_VAbv /* 18 chars; VAbv */
+#define _OT_VB OT_VBlw /* 7 chars; VBlw */
+#define _OT_VL OT_VPre /* 5 chars; VPre */
+#define _OT_VR OT_VPst /* 13 chars; VPst */
+#define _OT_VS OT_VS /* 16 chars; VS */
+#define _OT_X OT_X /* 2 chars; X */
+#define _OT_Xg OT_Xgroup /* 7 chars; Xgroup */
+#define _OT_Yg OT_Ygroup /* 4 chars; Ygroup */
+#define _OT_ZWJ OT_ZWJ /* 1 chars; ZWJ */
+#define _OT_ZWNJ OT_ZWNJ /* 1 chars; ZWNJ */
+
+#define _POS_T POS_ABOVE_C /* 22 chars; ABOVE_C */
+#define _POS_A POS_AFTER_MAIN /* 3 chars; AFTER_MAIN */
+#define _POS_AP POS_AFTER_POST /* 50 chars; AFTER_POST */
+#define _POS_AS POS_AFTER_SUB /* 51 chars; AFTER_SUB */
+#define _POS_C POS_BASE_C /* 833 chars; BASE_C */
+#define _POS_BS POS_BEFORE_SUB /* 25 chars; BEFORE_SUB */
+#define _POS_B POS_BELOW_C /* 13 chars; BELOW_C */
+#define _POS_X POS_END /* 71 chars; END */
+#define _POS_R POS_POST_C /* 13 chars; POST_C */
+#define _POS_L POS_PRE_C /* 5 chars; PRE_C */
+#define _POS_LM POS_PRE_M /* 14 chars; PRE_M */
+#define _POS_SM POS_SMVD /* 129 chars; SMVD */
+
+#pragma GCC diagnostic pop
+
+#define INDIC_COMBINE_CATEGORIES(S,M) ((S) | ((M) << 8))
+
+#define _(S,M) INDIC_COMBINE_CATEGORIES (_OT_##S, _POS_##M)
+
+
+static const uint16_t indic_table[] = {
+
+
+#define indic_offset_0x0028u 0
+
+
+ /* Basic Latin */
+
+ /* 0028 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X),
+ /* 0030 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0038 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x00b0u 24
+
+
+ /* Latin-1 Supplement */
+
+ /* 00B0 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00B8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C),
+
+#define indic_offset_0x0900u 64
+
+
+ /* Devanagari */
+
+ /* 0900 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0908 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0910 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0918 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0920 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0928 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0930 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0938 */ _(C,C), _(C,C), _(M,AS), _(M,AS), _(N,X), _(S,SM), _(M,AS), _(M,LM),
+ /* 0940 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS),
+ /* 0948 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(H,B), _(M,LM), _(M,AS),
+ /* 0950 */ _(X,X), _(A,SM), _(A,SM),_(SM,SM),_(SM,SM), _(M,AS), _(M,AS), _(M,AS),
+ /* 0958 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0960 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0968 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0970 */ _(X,X), _(X,X), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0978 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+ /* Bengali */
+
+ /* 0980 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0988 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0990 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0998 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09B0 */ _(R,C), _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 09B8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 09C0 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 09C8 */ _(M,LM), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(C,C), _(X,X),
+ /* 09D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 09D8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 09E0 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 09E8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 09F0 */ _(R,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 09F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X),_(SM,SM), _(X,X),
+
+ /* Gurmukhi */
+
+ /* 0A00 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A08 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0A10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0A38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(X,X), _(M,AP), _(M,LM),
+ /* 0A40 */ _(M,AP), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0A48 */ _(M,AP), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0A50 */ _(X,X), _(M,B), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0A58 */ _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X),
+ /* 0A60 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0A68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0A70 */_(SM,SM),_(SM,SM), _(C,C), _(C,C), _(X,X), _(CM,C), _(X,X), _(X,X),
+ /* 0A78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Gujarati */
+
+ /* 0A80 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C),
+ /* 0A90 */ _(V,C), _(V,C), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AB0 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0AB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 0AC0 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AS), _(X,X), _(M,AS),
+ /* 0AC8 */ _(M,AS), _(M,AP), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0AD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AE0 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0AE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0AF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AF8 */ _(X,X), _(C,C), _(A,SM), _(N,X), _(A,SM), _(N,X), _(N,X), _(N,X),
+
+ /* Oriya */
+
+ /* 0B00 */ _(X,X),_(SM,BS),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0B10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0B18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0B38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,A),
+ /* 0B40 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 0B48 */ _(M,A), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0B50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(N,X), _(M,A), _(M,AP),
+ /* 0B58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 0B60 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0B68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0B70 */ _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0B78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Tamil */
+
+ /* 0B80 */ _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B88 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(V,C), _(V,C),
+ /* 0B90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(X,X), _(X,X),
+ /* 0B98 */ _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X), _(C,C), _(C,C),
+ /* 0BA0 */ _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X),
+ /* 0BA8 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 0BB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0BB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP), _(M,AP),
+ /* 0BC0 */ _(M,AS), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(M,LM), _(M,LM),
+ /* 0BC8 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(X,X), _(X,X),
+ /* 0BD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0BD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BE0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0BE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0BF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Telugu */
+
+ /* 0C00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C),
+ /* 0C08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0C40 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,BS),
+ /* 0C48 */ _(M,BS), _(X,X), _(M,BS), _(M,BS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0C50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,BS), _(M,BS), _(X,X),
+ /* 0C58 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(C,C), _(X,X), _(X,X),
+ /* 0C60 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0C68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0C70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0C78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Kannada */
+
+ /* 0C80 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0C88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0CB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0CC0 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,AS),
+ /* 0CC8 */ _(M,AS), _(X,X), _(M,AS), _(M,AS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0CD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AS), _(M,AS), _(X,X),
+ /* 0CD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0CE0 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0CE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0CF0 */ _(X,X), _(CS,C), _(CS,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0CF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Malayalam */
+
+ /* 0D00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(GB,C), _(V,C), _(V,C), _(V,C),
+ /* 0D08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0D10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0D18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D28 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D38 */ _(C,C), _(C,C), _(C,C), _(M,AS), _(M,AS), _(S,SM), _(M,AP), _(M,AP),
+ /* 0D40 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(X,X), _(M,LM), _(M,LM),
+ /* 0D48 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(Rf,X), _(X,X),
+ /* 0D50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(M,AP),
+ /* 0D58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0D60 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0D68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0D70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0D78 */ _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+#define indic_offset_0x1000u 1216
+
+
+ /* Myanmar */
+
+ /* 1000 */ _(C,C), _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C),
+ /* 1008 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1010 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1018 */ _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1020 */ _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 1028 */ _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R), _(VA,T), _(VA,T), _(VB,B),
+ /* 1030 */ _(VB,B), _(VL,L), _(A,SM), _(VA,T), _(VA,T), _(VA,T), _(A,SM), _(N,X),
+ /* 1038 */_(SM,SM), _(H,X), _(As,X), _(MY,X), _(MR,X), _(MW,X), _(MH,X), _(C,C),
+ /* 1040 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1048 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X), _(C,C), _(X,X),
+ /* 1050 */ _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R),
+ /* 1058 */ _(VB,B), _(VB,B), _(R,C), _(C,C), _(C,C), _(C,C), _(MY,X), _(MY,X),
+ /* 1060 */ _(ML,X), _(C,C), _(VR,R), _(PT,X), _(PT,X), _(C,C), _(C,C), _(VR,R),
+ /* 1068 */ _(VR,R), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(C,C), _(C,C),
+ /* 1070 */ _(C,C), _(VA,T), _(VA,T), _(VA,T), _(VA,T), _(C,C), _(C,C), _(C,C),
+ /* 1078 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1080 */ _(C,C), _(C,C), _(MW,X), _(VR,R), _(VL,L), _(VA,T), _(VA,T),_(SM,SM),
+ /* 1088 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(C,C),_(SM,SM),
+ /* 1090 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1098 */ _(GB,C), _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(VA,T), _(X,X), _(X,X),
+
+#define indic_offset_0x1780u 1376
+
+
+ /* Khmer */
+
+ /* 1780 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1788 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1790 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1798 */ _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 17A0 */ _(C,C), _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17A8 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17B0 */ _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(VR,R), _(VA,T),
+ /* 17B8 */ _(VA,T), _(VA,T), _(VA,T), _(VB,B), _(VB,B), _(VB,B), _(VA,T), _(VR,R),
+ /* 17C0 */ _(VR,R), _(VL,L), _(VL,L), _(VL,L), _(VR,R), _(VR,R), _(Xg,X), _(Yg,X),
+ /* 17C8 */ _(Yg,X), _(Rt,X), _(Rt,X), _(Xg,X), _(Rt,X), _(Xg,X), _(Xg,X), _(Xg,X),
+ /* 17D0 */ _(Xg,X), _(Xg,X), _(H,X), _(Yg,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 17D8 */ _(X,X), _(GB,C), _(X,X), _(X,X), _(S,SM), _(Yg,X), _(X,X), _(X,X),
+ /* 17E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 17E8 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x1cd0u 1488
+
+
+ /* Vedic Extensions */
+
+ /* 1CD0 */ _(A,SM), _(A,SM), _(A,SM), _(X,X), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CD8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE8 */ _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(A,SM), _(S,SM), _(S,SM),
+ /* 1CF0 */ _(S,SM), _(S,SM), _(C,C), _(C,C), _(A,SM), _(C,C), _(C,C), _(A,SM),
+ /* 1CF8 */ _(A,SM), _(A,SM), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2008u 1536
+
+
+ /* General Punctuation */
+
+ /* 2008 */ _(X,X), _(X,X), _(X,X), _(X,X),_(ZWNJ,X),_(ZWJ,X), _(X,X), _(X,X),
+ /* 2010 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X),
+ /* 2018 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2020 */ _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2070u 1568
+
+
+ /* Superscripts and Subscripts */
+
+ /* 2070 */ _(X,X), _(X,X), _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(X,X),
+ /* 2078 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2080 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x25f8u 1592
+
+
+ /* Geometric Shapes */
+
+ /* 25F8 */ _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+
+#define indic_offset_0xa8e0u 1600
+
+
+ /* Devanagari Extended */
+
+ /* A8E0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8E8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8F0 */ _(A,SM), _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM),
+ /* A8F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C), _(M,AS),
+
+#define indic_offset_0xa9e0u 1632
+
+
+ /* Myanmar Extended-B */
+
+ /* A9E0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(VA,T), _(X,X), _(C,C),
+ /* A9E8 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* A9F0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* A9F8 */ _(GB,C), _(GB,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X),
+
+#define indic_offset_0xaa60u 1664
+
+
+ /* Myanmar Extended-A */
+
+ /* AA60 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA68 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA70 */ _(X,X), _(C,C), _(C,C), _(C,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+ /* AA78 */ _(X,X), _(X,X), _(C,C), _(PT,X), _(N,X), _(N,X), _(C,C), _(C,C),
+
+#define indic_offset_0xfe00u 1696
+
+
+ /* Variation Selectors */
+
+ /* FE00 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+ /* FE08 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+
+#define indic_offset_0x11300u 1712
+
+
+ /* Grantha */
+
+ /* 11300 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11308 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11310 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11318 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11320 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11328 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11330 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X),
+
+}; /* Table items: 1776; occupancy: 69% */
+
+uint16_t
+hb_indic_get_categories (hb_codepoint_t u)
+{
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (unlikely (u == 0x00A0u)) return _(GB,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0D7Fu)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+ break;
+
+ case 0x1u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ break;
+
+ case 0x2u:
+ if (unlikely (u == 0x25CCu)) return _(DC,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2027u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x25F8u, 0x25FFu)) return indic_table[u - 0x25F8u + indic_offset_0x25f8u];
+ break;
+
+ case 0xAu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
+ break;
+
+ case 0xFu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return indic_table[u - 0xFE00u + indic_offset_0xfe00u];
+ break;
+
+ case 0x11u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x1133Fu)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+ break;
+
+ default:
+ break;
+ }
+ return _(X,X);
+}
+
+#undef _
+#undef INDIC_COMBINE_CATEGORIES
+
+#undef _OT_A
+#undef _OT_As
+#undef _OT_C
+#undef _OT_CM
+#undef _OT_CS
+#undef _OT_DC
+#undef _OT_H
+#undef _OT_M
+#undef _OT_MH
+#undef _OT_ML
+#undef _OT_MR
+#undef _OT_MW
+#undef _OT_MY
+#undef _OT_N
+#undef _OT_GB
+#undef _OT_PT
+#undef _OT_R
+#undef _OT_Rf
+#undef _OT_Rt
+#undef _OT_SM
+#undef _OT_S
+#undef _OT_V
+#undef _OT_VA
+#undef _OT_VB
+#undef _OT_VL
+#undef _OT_VR
+#undef _OT_VS
+#undef _OT_X
+#undef _OT_Xg
+#undef _OT_Yg
+#undef _OT_ZWJ
+#undef _OT_ZWNJ
+
+#undef _POS_T
+#undef _POS_A
+#undef _POS_AP
+#undef _POS_AS
+#undef _POS_C
+#undef _POS_BS
+#undef _POS_B
+#undef _POS_X
+#undef _POS_R
+#undef _POS_L
+#undef _POS_LM
+#undef _POS_SM
+
+#endif
+
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
index c80f7df6a9..48a3c74463 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
@@ -28,9 +28,9 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-indic.hh"
-#include "hb-ot-shape-complex-indic-machine.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
#include "hb-ot-layout.hh"
@@ -39,6 +39,81 @@
*/
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.indic_category() = (indic_category_t) (type & 0xFFu);
+ info.indic_position() = (indic_position_t) (type >> 8);
+}
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_INDIC (FLAG (I_Cat(C)) | FLAG (I_Cat(CS)) | FLAG (I_Cat(Ra)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(V)) | FLAG (I_Cat(PLACEHOLDER)) | FLAG (I_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, CONSONANT_FLAGS_INDIC);
+}
+
+#define JOINER_FLAGS (FLAG (I_Cat(ZWJ)) | FLAG (I_Cat(ZWNJ)))
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, FLAG (I_Cat(H)));
+}
+
+struct hb_indic_would_substitute_feature_t
+{
+ void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+ {
+ zero_context = zero_context_;
+ map->get_stage_lookups (0/*GSUB*/,
+ map->get_feature_stage (0/*GSUB*/, feature_tag),
+ &lookups, &count);
+ }
+
+ bool would_substitute (const hb_codepoint_t *glyphs,
+ unsigned int glyphs_count,
+ hb_face_t *face) const
+ {
+ for (unsigned int i = 0; i < count; i++)
+ if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
+ return true;
+ return false;
+ }
+
+ private:
+ const hb_ot_map_t::lookup_map_t *lookups;
+ unsigned int count;
+ bool zero_context;
+};
+
+
/*
* Indic configurations. Note that we do not want to keep every single script-specific
* behavior in these tables necessarily. This should mainly be used for per-script
@@ -47,10 +122,6 @@
* instead of adding a new flag in these structs.
*/
-enum base_position_t {
- BASE_POS_LAST_SINHALA,
- BASE_POS_LAST
-};
enum reph_position_t {
REPH_POS_AFTER_MAIN = POS_AFTER_MAIN,
REPH_POS_BEFORE_SUB = POS_BEFORE_SUB,
@@ -72,7 +143,6 @@ struct indic_config_t
hb_script_t script;
bool has_old_spec;
hb_codepoint_t virama;
- base_position_t base_pos;
reph_position_t reph_pos;
reph_mode_t reph_mode;
blwf_mode_t blwf_mode;
@@ -81,26 +151,19 @@ struct indic_config_t
static const indic_config_t indic_configs[] =
{
/* Default. Should be first. */
- {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
- REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_INVALID, false, 0,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_DEVANAGARI,true, 0x094Du,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_BENGALI, true, 0x09CDu,REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GUJARATI, true, 0x0ACDu,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_ORIYA, true, 0x0B4Du,REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TAMIL, true, 0x0BCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TELUGU, true, 0x0C4Du,REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_KANNADA, true, 0x0CCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
};
-
-/*
- * Indic shaper.
- */
-
static const hb_ot_map_feature_t
indic_features[] =
{
@@ -207,6 +270,7 @@ static void
override_features_indic (hb_ot_shape_planner_t *plan)
{
plan->map.disable_feature (HB_TAG('l','i','g','a'));
+ plan->map.add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
}
@@ -356,6 +420,7 @@ setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_indic (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
@@ -367,7 +432,7 @@ compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
int a = pa->indic_position();
int b = pb->indic_position();
- return a < b ? -1 : a == b ? 0 : +1;
+ return (int) a - (int) b;
}
@@ -379,9 +444,6 @@ update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
- if (indic_plan->config->base_pos != BASE_POS_LAST)
- return;
-
hb_codepoint_t virama;
if (indic_plan->load_virama_glyph (font, &virama))
{
@@ -416,9 +478,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
*/
if (buffer->props.script == HB_SCRIPT_KANNADA &&
start + 3 <= end &&
- is_one_of (info[start ], FLAG (OT_Ra)) &&
- is_one_of (info[start+1], FLAG (OT_H)) &&
- is_one_of (info[start+2], FLAG (OT_ZWJ)))
+ is_one_of (info[start ], FLAG (I_Cat(Ra))) &&
+ is_one_of (info[start+1], FLAG (I_Cat(H))) &&
+ is_one_of (info[start+2], FLAG (I_Cat(ZWJ))))
{
buffer->merge_clusters (start+1, start+3);
hb_glyph_info_t tmp = info[start+1];
@@ -452,7 +514,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
start + 3 <= end &&
(
(indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
- (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == OT_ZWJ)
+ (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == I_Cat(ZWJ))
))
{
/* See if it matches the 'rphf' feature. */
@@ -470,7 +532,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
base = start;
has_reph = true;
}
- } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == OT_Repha)
+ } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == I_Cat(Repha))
{
limit += 1;
while (limit < end && is_joiner (info[limit]))
@@ -479,84 +541,51 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
has_reph = true;
}
- switch (indic_plan->config->base_pos)
{
- case BASE_POS_LAST:
- {
- /* -> starting from the end of the syllable, move backwards */
- unsigned int i = end;
- bool seen_below = false;
- do {
- i--;
- /* -> until a consonant is found */
- if (is_consonant (info[i]))
+ /* -> starting from the end of the syllable, move backwards */
+ unsigned int i = end;
+ bool seen_below = false;
+ do {
+ i--;
+ /* -> until a consonant is found */
+ if (is_consonant (info[i]))
+ {
+ /* -> that does not have a below-base or post-base form
+ * (post-base forms have to follow below-base forms), */
+ if (info[i].indic_position() != POS_BELOW_C &&
+ (info[i].indic_position() != POS_POST_C || seen_below))
{
- /* -> that does not have a below-base or post-base form
- * (post-base forms have to follow below-base forms), */
- if (info[i].indic_position() != POS_BELOW_C &&
- (info[i].indic_position() != POS_POST_C || seen_below))
- {
- base = i;
- break;
- }
- if (info[i].indic_position() == POS_BELOW_C)
- seen_below = true;
-
- /* -> or that is not a pre-base-reordering Ra,
- *
- * IMPLEMENTATION NOTES:
- *
- * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
- * by the logic above already.
- */
-
- /* -> or arrive at the first consonant. The consonant stopped at will
- * be the base. */
base = i;
+ break;
}
- else
- {
- /* A ZWJ after a Halant stops the base search, and requests an explicit
- * half form.
- * A ZWJ before a Halant, requests a subjoined form instead, and hence
- * search continues. This is particularly important for Bengali
- * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
- if (start < i &&
- info[i].indic_category() == OT_ZWJ &&
- info[i - 1].indic_category() == OT_H)
- break;
- }
- } while (i > limit);
- }
- break;
-
- case BASE_POS_LAST_SINHALA:
- {
- /* Sinhala base positioning is slightly different from main Indic, in that:
- * 1. Its ZWJ behavior is different,
- * 2. We don't need to look into the font for consonant positions.
- */
-
- if (!has_reph)
- base = limit;
+ if (info[i].indic_position() == POS_BELOW_C)
+ seen_below = true;
- /* Find the last base consonant that is not blocked by ZWJ. If there is
- * a ZWJ right before a base consonant, that would request a subjoined form. */
- for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
- {
- if (limit < i && info[i - 1].indic_category() == OT_ZWJ)
- break;
- else
- base = i;
- }
+ /* -> or that is not a pre-base-reordering Ra,
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
+ * by the logic above already.
+ */
- /* Mark all subsequent consonants as below. */
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
- info[i].indic_position() = POS_BELOW_C;
- }
- break;
+ /* -> or arrive at the first consonant. The consonant stopped at will
+ * be the base. */
+ base = i;
+ }
+ else
+ {
+ /* A ZWJ after a Halant stops the base search, and requests an explicit
+ * half form.
+ * A ZWJ before a Halant, requests a subjoined form instead, and hence
+ * search continues. This is particularly important for Bengali
+ * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
+ if (start < i &&
+ info[i].indic_category() == I_Cat(ZWJ) &&
+ info[i - 1].indic_category() == I_Cat(H))
+ break;
+ }
+ } while (i > limit);
}
/* -> If the syllable starts with Ra + Halant (in a script that has Reph)
@@ -611,18 +640,6 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (base < end)
info[base].indic_position() = POS_BASE_C;
- /* Mark final consonants. A final consonant is one appearing after a matra.
- * Happens in Sinhala. */
- for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_M) {
- for (unsigned int j = i + 1; j < end; j++)
- if (is_consonant (info[j])) {
- info[j].indic_position() = POS_FINAL_C;
- break;
- }
- break;
- }
-
/* Handle beginning Ra */
if (has_reph)
info[start].indic_position() = POS_RA_TO_BECOME_REPH;
@@ -659,14 +676,14 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
{
bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_H)
+ if (info[i].indic_category() == I_Cat(H))
{
unsigned int j;
for (j = end - 1; j > i; j--)
if (is_consonant (info[j]) ||
- (disallow_double_halants && info[j].indic_category() == OT_H))
+ (disallow_double_halants && info[j].indic_category() == I_Cat(H)))
break;
- if (info[j].indic_category() != OT_H && j > i) {
+ if (info[j].indic_category() != I_Cat(H) && j > i) {
/* Move Halant to after last consonant. */
hb_glyph_info_t t = info[i];
memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
@@ -681,20 +698,16 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
indic_position_t last_pos = POS_START;
for (unsigned int i = start; i < end; i++)
{
- if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
+ if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (I_Cat(N)) | FLAG (I_Cat(RS)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(H)))))
{
info[i].indic_position() = last_pos;
- if (unlikely (info[i].indic_category() == OT_H &&
+ if (unlikely (info[i].indic_category() == I_Cat(H) &&
info[i].indic_position() == POS_PRE_M))
{
/*
* Uniscribe doesn't move the Halant with Left Matra.
- * TEST: U+092B,U+093F,U+094DE
- * We follow. This is important for the Sinhala
- * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
- * where U+0DD9 is a left matra and U+0DCA is the virama.
- * We don't want to move the virama with the left matra.
- * TEST: U+0D9A,U+0DDA
+ * TEST: U+092B,U+093F,U+094D
+ * We follow.
*/
for (unsigned int j = i; j > start; j--)
if (info[j - 1].indic_position() != POS_PRE_M) {
@@ -718,7 +731,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
if (info[j].indic_position() < POS_SMVD)
info[j].indic_position() = info[i].indic_position();
last = i;
- } else if (info[i].indic_category() == OT_M)
+ } else if (info[i].indic_category() == I_Cat(M))
last = i;
}
@@ -849,10 +862,10 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
* Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
*/
for (unsigned int i = start; i + 1 < base; i++)
- if (info[i ].indic_category() == OT_Ra &&
- info[i+1].indic_category() == OT_H &&
+ if (info[i ].indic_category() == I_Cat(Ra) &&
+ info[i+1].indic_category() == I_Cat(H) &&
(i + 2 == base ||
- info[i+2].indic_category() != OT_ZWJ))
+ info[i+2].indic_category() != I_Cat(ZWJ)))
{
info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
@@ -879,7 +892,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
/* Apply ZWJ/ZWNJ effects */
for (unsigned int i = start + 1; i < end; i++)
if (is_joiner (info[i])) {
- bool non_joiner = info[i].indic_category() == OT_ZWNJ;
+ bool non_joiner = info[i].indic_category() == I_Cat(ZWNJ);
unsigned int j = i;
do {
@@ -912,7 +925,7 @@ initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
/* For dotted-circle, this is what Uniscribe does:
* If dotted-circle is the last glyph, it just does nothing.
* Ie. It doesn't form Reph. */
- if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
+ if (buffer->info[end - 1].indic_category() == I_Cat(DOTTEDCIRCLE))
return;
}
@@ -955,8 +968,8 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan,
update_consonant_positions_indic (plan, font, buffer);
hb_syllabic_insert_dotted_circles (font, buffer,
indic_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha,
+ I_Cat(DOTTEDCIRCLE),
+ I_Cat(Repha),
POS_END);
foreach_syllable (buffer, start, end)
@@ -978,7 +991,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
* and possibly multiple substitutions happened prior to this
* phase, and that might have messed up our properties. Recover
* from a particular case of that where we're fairly sure that a
- * class of OT_H is desired but has been lost. */
+ * class of I_Cat(H) is desired but has been lost. */
/* We don't call load_virama_glyph(), since we know it's already
* loaded. */
hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
@@ -990,7 +1003,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
_hb_glyph_info_multiplied (&info[i]))
{
/* This will make sure that this glyph passes is_halant() test. */
- info[i].indic_category() = OT_H;
+ info[i].indic_category() = I_Cat(H);
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
}
}
@@ -1056,11 +1069,11 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
break;
}
if (base == end && start < base &&
- is_one_of (info[base - 1], FLAG (OT_ZWJ)))
+ is_one_of (info[base - 1], FLAG (I_Cat(ZWJ))))
base--;
if (base < end)
while (start < base &&
- is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_H))))
+ is_one_of (info[base], (FLAG (I_Cat(N)) | FLAG (I_Cat(H)))))
base--;
@@ -1105,7 +1118,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
{
search:
while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
+ !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(H))))))
new_pos--;
/* If we found no Halant we are done.
@@ -1122,7 +1135,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
if (new_pos + 1 < end)
{
/* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
- if (info[new_pos + 1].indic_category() == OT_ZWJ)
+ if (info[new_pos + 1].indic_category() == I_Cat(ZWJ))
{
/* Keep searching. */
if (new_pos > start)
@@ -1195,7 +1208,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
*/
if (start + 1 < end &&
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
- ((info[start].indic_category() == OT_Repha) ^
+ ((info[start].indic_category() == I_Cat(Repha)) ^
_hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
{
unsigned int new_reph_pos;
@@ -1305,7 +1318,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
unlikely (is_halant (info[new_reph_pos])))
{
for (unsigned int i = base + 1; i < new_reph_pos; i++)
- if (info[i].indic_category() == OT_M) {
+ if (info[i].indic_category() == I_Cat(M)) {
/* Ok, got it. */
new_reph_pos--;
}
@@ -1365,7 +1378,7 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
{
while (new_pos > start &&
- !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_H))))
+ !(is_one_of (info[new_pos - 1], FLAG(I_Cat(M)) | FLAG (I_Cat(H)))))
new_pos--;
}
@@ -1414,11 +1427,10 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
switch ((hb_tag_t) plan->props.script)
{
case HB_SCRIPT_TAMIL:
- case HB_SCRIPT_SINHALA:
break;
default:
- /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
+ /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil.
* This means, half forms are submerged into the main consonant's cluster.
* This is unnecessary, and makes cursor positioning harder, but that's what
* Uniscribe does. */
@@ -1453,7 +1465,9 @@ preprocess_text_indic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font)
{
- _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ if (!indic_plan->uniscribe_bug_compatible)
+ _hb_preprocess_text_vowel_constraints (plan, buffer, font);
}
static bool
@@ -1486,48 +1500,6 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
#endif
}
- if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu)))
- {
- /*
- * Sinhala split matras... Let the fun begin.
- *
- * These four characters have Unicode decompositions. However, Uniscribe
- * decomposes them "Khmer-style", that is, it uses the character itself to
- * get the second half. The first half of all four decompositions is always
- * U+0DD9.
- *
- * Now, there are buggy fonts, namely, the widely used lklug.ttf, that are
- * broken with Uniscribe. But we need to support them. As such, we only
- * do the Uniscribe-style decomposition if the character is transformed into
- * its "sec.half" form by the 'pstf' feature. Otherwise, we fall back to
- * Unicode decomposition.
- *
- * Note that we can't unconditionally use Unicode decomposition. That would
- * break some other fonts, that are designed to work with Uniscribe, and
- * don't have positioning features for the Unicode-style decomposition.
- *
- * Argh...
- *
- * The Uniscribe behavior is now documented in the newly published Sinhala
- * spec in 2012:
- *
- * https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
- */
-
-
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
- hb_codepoint_t glyph;
- if (indic_plan->uniscribe_bug_compatible ||
- (c->font->get_nominal_glyph (ab, &glyph) &&
- indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
- {
- /* Ok, safe to use Uniscribe-style decomposition. */
- *a = 0x0DD9u;
- *b = ab;
- return true;
- }
- }
-
return (bool) c->unicode->decompose (ab, a, b);
}
@@ -1548,7 +1520,7 @@ compose_indic (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
+const hb_ot_shaper_t _hb_ot_shaper_indic =
{
collect_features_indic,
override_features_indic,
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh
new file mode 100644
index 0000000000..4f822c26e9
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_INDIC_HH
+#define HB_OT_SHAPER_INDIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-syllabic.hh"
+
+
+/* Visual positions in a syllable from left to right. */
+enum ot_position_t {
+ POS_START = 0,
+
+ POS_RA_TO_BECOME_REPH = 1,
+ POS_PRE_M = 2,
+ POS_PRE_C = 3,
+
+ POS_BASE_C = 4,
+ POS_AFTER_MAIN = 5,
+
+ POS_ABOVE_C = 6,
+
+ POS_BEFORE_SUB = 7,
+ POS_BELOW_C = 8,
+ POS_AFTER_SUB = 9,
+
+ POS_BEFORE_POST = 10,
+ POS_POST_C = 11,
+ POS_AFTER_POST = 12,
+
+ POS_SMVD = 13,
+
+ POS_END = 14
+};
+
+
+HB_INTERNAL uint16_t
+hb_indic_get_categories (hb_codepoint_t u);
+
+
+#endif /* HB_OT_SHAPER_INDIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
new file mode 100644
index 0000000000..e18bd75ef1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
@@ -0,0 +1,428 @@
+
+#line 1 "hb-ot-shaper-khmer-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_KHMER_MACHINE_HH
+#define HB_OT_SHAPER_KHMER_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define khmer_category() ot_shaper_var_u8_category() /* khmer_category_t */
+
+using khmer_category_t = unsigned;
+
+#define K_Cat(Cat) khmer_syllable_machine_ex_##Cat
+
+enum khmer_syllable_type_t {
+ khmer_consonant_syllable,
+ khmer_broken_cluster,
+ khmer_non_khmer_cluster,
+};
+
+
+#line 52 "hb-ot-shaper-khmer-machine.hh"
+#define khmer_syllable_machine_ex_C 1u
+#define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define khmer_syllable_machine_ex_H 4u
+#define khmer_syllable_machine_ex_PLACEHOLDER 10u
+#define khmer_syllable_machine_ex_Ra 15u
+#define khmer_syllable_machine_ex_Robatic 25u
+#define khmer_syllable_machine_ex_V 2u
+#define khmer_syllable_machine_ex_VAbv 20u
+#define khmer_syllable_machine_ex_VBlw 21u
+#define khmer_syllable_machine_ex_VPre 22u
+#define khmer_syllable_machine_ex_VPst 23u
+#define khmer_syllable_machine_ex_Xgroup 26u
+#define khmer_syllable_machine_ex_Ygroup 27u
+#define khmer_syllable_machine_ex_ZWJ 6u
+#define khmer_syllable_machine_ex_ZWNJ 5u
+
+
+#line 70 "hb-ot-shaper-khmer-machine.hh"
+static const unsigned char _khmer_syllable_machine_trans_keys[] = {
+ 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 27u, 4u, 27u, 1u, 15u,
+ 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 1u, 15u, 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 4u, 27u, 5u, 26u, 0
+};
+
+static const char _khmer_syllable_machine_key_spans[] = {
+ 22, 22, 15, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 15, 22, 22,
+ 22, 22, 22, 22, 22, 27, 24, 15,
+ 24, 24, 1, 24, 24, 24, 24, 24,
+ 24, 15, 24, 24, 1, 24, 24, 24,
+ 24, 24, 22
+};
+
+static const short _khmer_syllable_machine_index_offsets[] = {
+ 0, 23, 46, 62, 85, 108, 131, 154,
+ 177, 200, 223, 246, 269, 292, 308, 331,
+ 354, 377, 400, 423, 446, 469, 497, 522,
+ 538, 563, 588, 590, 615, 640, 665, 690,
+ 715, 740, 756, 781, 806, 808, 833, 858,
+ 883, 908, 933
+};
+
+static const char _khmer_syllable_machine_indicies[] = {
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 3, 4, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 4, 0, 6, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 7, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 9, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0,
+ 10, 0, 9, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 11, 11, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 12, 0,
+ 11, 11, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 12, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 13, 4, 0, 15, 15,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 16, 14, 14,
+ 14, 14, 17, 18, 14, 15, 15, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 18, 19, 20, 20, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 20, 14, 15, 15, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 16, 14, 14, 14, 14,
+ 14, 18, 14, 21, 21, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 22, 22, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 23,
+ 14, 24, 24, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 14, 14, 14, 14, 25, 14,
+ 24, 24, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 25, 14, 26,
+ 26, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 16, 14,
+ 14, 14, 14, 14, 27, 14, 26, 26,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 27, 14, 29, 29, 28,
+ 30, 31, 31, 28, 28, 28, 13, 13,
+ 28, 28, 28, 29, 28, 28, 28, 28,
+ 16, 25, 27, 23, 28, 17, 18, 20,
+ 28, 33, 34, 34, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 12, 8, 32, 13, 4,
+ 5, 32, 35, 35, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 35, 32, 33, 36, 36, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 3,
+ 4, 5, 32, 37, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 32, 4, 5, 32, 5, 32, 37, 6,
+ 6, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 8, 32, 32, 2, 5, 32, 37,
+ 7, 7, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 8, 5, 32,
+ 37, 39, 39, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 32, 32, 8, 32, 32, 10, 5,
+ 32, 37, 40, 40, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 32, 8, 32, 32, 12,
+ 5, 32, 33, 38, 38, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 32,
+ 4, 5, 32, 33, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 3, 4, 5, 32, 42, 42, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 42, 41, 30, 43, 43, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 17, 18, 20, 41, 44, 45, 45,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 16, 25, 27,
+ 23, 41, 41, 18, 20, 41, 20, 41,
+ 44, 21, 21, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 23, 41, 41, 16, 20,
+ 41, 44, 22, 22, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 23,
+ 20, 41, 44, 46, 46, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 16, 41, 41, 23, 41, 41,
+ 25, 20, 41, 44, 47, 47, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 16, 25, 41, 23, 41,
+ 41, 27, 20, 41, 30, 45, 45, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 41, 18, 20, 41, 15, 15, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 16, 48, 48, 48,
+ 48, 48, 18, 48, 0
+};
+
+static const char _khmer_syllable_machine_trans_targs[] = {
+ 21, 1, 27, 31, 25, 26, 4, 5,
+ 28, 7, 29, 9, 30, 32, 21, 12,
+ 37, 41, 35, 21, 36, 15, 16, 38,
+ 18, 39, 20, 40, 21, 22, 33, 42,
+ 21, 23, 10, 24, 0, 2, 3, 6,
+ 8, 21, 34, 11, 13, 14, 17, 19,
+ 21
+};
+
+static const char _khmer_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 2, 0, 2, 2, 3, 0,
+ 2, 4, 4, 5, 0, 0, 0, 2,
+ 0, 2, 0, 2, 8, 2, 0, 9,
+ 10, 0, 0, 2, 0, 0, 0, 0,
+ 0, 11, 4, 0, 0, 0, 0, 0,
+ 12
+};
+
+static const char _khmer_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const char _khmer_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const short _khmer_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 15, 20, 15, 15, 15,
+ 15, 15, 15, 15, 15, 0, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 49
+};
+
+static const int khmer_syllable_machine_start = 21;
+static const int khmer_syllable_machine_first_final = 21;
+static const int khmer_syllable_machine_error = -1;
+
+static const int khmer_syllable_machine_en_main = 21;
+
+
+#line 53 "hb-ot-shaper-khmer-machine.rl"
+
+
+
+#line 102 "hb-ot-shaper-khmer-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_khmer (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 298 "hb-ot-shaper-khmer-machine.hh"
+ {
+ cs = khmer_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 122 "hb-ot-shaper-khmer-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 314 "hb-ot-shaper-khmer-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
+ case 7:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 328 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
+ _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
+
+ _slen = _khmer_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
+ ( info[p].khmer_category()) <= _keys[1] ?
+ ( info[p].khmer_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _khmer_syllable_machine_trans_targs[_trans];
+
+ if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 8:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 10:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 11:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 12:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 1:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 3:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 5:
+#line 1 "NONE"
+ { switch( act ) {
+ case 2:
+ {{p = ((te))-1;} found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 3:
+ {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
+ break;
+ }
+ }
+ break;
+ case 4:
+#line 1 "NONE"
+ {te = p+1;}
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {act = 2;}
+ break;
+ case 9:
+#line 1 "NONE"
+ {te = p+1;}
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {act = 3;}
+ break;
+#line 398 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+_again:
+ switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+ case 6:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 407 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 130 "hb-ot-shaper-khmer-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_KHMER_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
index a7d5bf574b..e04d633195 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
@@ -28,8 +28,8 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-khmer.hh"
-#include "hb-ot-shape-complex-khmer-machine.hh"
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-indic.hh"
#include "hb-ot-layout.hh"
@@ -37,6 +37,7 @@
* Khmer shaper.
*/
+
static const hb_ot_map_feature_t
khmer_features[] =
{
@@ -79,6 +80,15 @@ enum {
KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
};
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.khmer_category() = (khmer_category_t) (type & 0xFFu);
+}
+
static void
setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
@@ -115,7 +125,7 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
map->add_feature (khmer_features[i]);
/* https://github.com/harfbuzz/harfbuzz/issues/3531 */
- map->add_gsub_pause (nullptr);
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
for (; i < KHMER_NUM_FEATURES; i++)
map->add_feature (khmer_features[i]);
@@ -187,6 +197,7 @@ setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_khmer (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
@@ -230,11 +241,11 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
* the 'pref' OpenType feature applied to them.
* """
*/
- if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+ if (info[i].khmer_category() == K_Cat(H) && num_coengs <= 2 && i + 1 < end)
{
num_coengs++;
- if (info[i + 1].khmer_category() == OT_Ra)
+ if (info[i + 1].khmer_category() == K_Cat(Ra))
{
for (unsigned int j = 0; j < 2; j++)
info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
@@ -262,7 +273,7 @@ reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
}
/* Reorder left matra piece. */
- else if (info[i].khmer_category() == OT_VPre)
+ else if (info[i].khmer_category() == K_Cat(VPre))
{
/* Move to the start. */
buffer->merge_clusters (start, i + 1);
@@ -301,8 +312,8 @@ reorder_khmer (const hb_ot_shape_plan_t *plan,
{
hb_syllabic_insert_dotted_circles (font, buffer,
khmer_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha);
+ K_Cat(DOTTEDCIRCLE),
+ (unsigned) -1);
foreach_syllable (buffer, start, end)
reorder_syllable_khmer (plan, font->face, buffer, start, end);
@@ -349,7 +360,7 @@ compose_khmer (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
+const hb_ot_shaper_t _hb_ot_shaper_khmer =
{
collect_features_khmer,
override_features_khmer,
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
new file mode 100644
index 0000000000..b109708937
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
@@ -0,0 +1,553 @@
+
+#line 1 "hb-ot-shaper-myanmar-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_MYANMAR_MACHINE_HH
+#define HB_OT_SHAPER_MYANMAR_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define myanmar_category() ot_shaper_var_u8_category() /* myanmar_category_t */
+#define myanmar_position() ot_shaper_var_u8_auxiliary() /* myanmar_position_t */
+
+using myanmar_category_t = unsigned;
+using myanmar_position_t = ot_position_t;
+
+#define M_Cat(Cat) myanmar_syllable_machine_ex_##Cat
+
+enum myanmar_syllable_type_t {
+ myanmar_consonant_syllable,
+ myanmar_broken_cluster,
+ myanmar_non_myanmar_cluster,
+};
+
+
+#line 54 "hb-ot-shaper-myanmar-machine.hh"
+#define myanmar_syllable_machine_ex_A 9u
+#define myanmar_syllable_machine_ex_As 32u
+#define myanmar_syllable_machine_ex_C 1u
+#define myanmar_syllable_machine_ex_CS 18u
+#define myanmar_syllable_machine_ex_DB 3u
+#define myanmar_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define myanmar_syllable_machine_ex_GB 10u
+#define myanmar_syllable_machine_ex_H 4u
+#define myanmar_syllable_machine_ex_IV 2u
+#define myanmar_syllable_machine_ex_MH 35u
+#define myanmar_syllable_machine_ex_ML 41u
+#define myanmar_syllable_machine_ex_MR 36u
+#define myanmar_syllable_machine_ex_MW 37u
+#define myanmar_syllable_machine_ex_MY 38u
+#define myanmar_syllable_machine_ex_PT 39u
+#define myanmar_syllable_machine_ex_Ra 15u
+#define myanmar_syllable_machine_ex_SM 8u
+#define myanmar_syllable_machine_ex_VAbv 20u
+#define myanmar_syllable_machine_ex_VBlw 21u
+#define myanmar_syllable_machine_ex_VPre 22u
+#define myanmar_syllable_machine_ex_VPst 23u
+#define myanmar_syllable_machine_ex_VS 40u
+#define myanmar_syllable_machine_ex_ZWJ 6u
+#define myanmar_syllable_machine_ex_ZWNJ 5u
+
+
+#line 81 "hb-ot-shaper-myanmar-machine.hh"
+static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
+ 1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+ 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u,
+ 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 41u,
+ 3u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+ 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 41u, 3u, 39u,
+ 3u, 39u, 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u,
+ 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 1u, 41u, 1u, 15u, 0
+};
+
+static const char _myanmar_syllable_machine_key_spans[] = {
+ 41, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 37, 37,
+ 38, 37, 39, 39, 37, 39, 39, 39,
+ 39, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 39, 37,
+ 37, 38, 37, 39, 39, 37, 39, 39,
+ 39, 39, 39, 39, 39, 41, 15
+};
+
+static const short _myanmar_syllable_machine_index_offsets[] = {
+ 0, 42, 82, 118, 123, 163, 201, 239,
+ 275, 311, 349, 387, 427, 463, 479, 517,
+ 555, 594, 632, 672, 712, 750, 790, 830,
+ 870, 910, 950, 986, 991, 1031, 1069, 1107,
+ 1143, 1179, 1217, 1255, 1295, 1331, 1347, 1387,
+ 1425, 1463, 1502, 1540, 1580, 1620, 1658, 1698,
+ 1738, 1778, 1818, 1858, 1898, 1938, 1980
+};
+
+static const char _myanmar_syllable_machine_indicies[] = {
+ 1, 1, 2, 3, 4, 4, 0, 5,
+ 6, 1, 1, 0, 0, 0, 7, 0,
+ 0, 8, 0, 9, 10, 11, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 14, 15, 16, 17, 18, 19,
+ 20, 0, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 24, 24, 21, 25, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 39, 21, 21,
+ 21, 21, 21, 21, 36, 21, 24, 24,
+ 21, 25, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 42, 21, 21, 21, 36,
+ 21, 41, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 21, 43, 21, 24, 24, 21, 25, 36,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 44, 21,
+ 21, 21, 21, 21, 21, 36, 21, 24,
+ 24, 21, 25, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 44, 21, 21, 21, 21, 21,
+ 21, 36, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 40, 21, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 40, 21,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 41, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 21, 21, 21, 21, 36,
+ 21, 41, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 30, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 1,
+ 1, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 1, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 27, 28, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 27, 28, 29, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 45, 21, 22, 21, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 36, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 31, 21, 21,
+ 32, 33, 34, 35, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 21,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 45, 21, 21, 32, 21,
+ 21, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 46, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 23,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 31, 21, 21, 32, 33,
+ 34, 35, 36, 21, 38, 21, 48, 48,
+ 47, 5, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 49, 47, 47, 47, 47, 47, 47,
+ 18, 47, 48, 48, 47, 5, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 52,
+ 47, 47, 47, 18, 47, 51, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 47, 53, 47, 48,
+ 48, 47, 5, 18, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 54, 47, 47, 47, 47, 47,
+ 47, 18, 47, 48, 48, 47, 5, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 54, 47,
+ 47, 47, 47, 47, 47, 18, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 50, 47, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 50, 47, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 51, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 47,
+ 47, 47, 47, 18, 47, 51, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 12, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 55, 55, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 55, 47, 2, 3, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 11, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 13, 47, 47, 14, 15, 16, 17, 18,
+ 19, 20, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 10, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 9, 10, 11, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 56, 47, 2, 47,
+ 48, 48, 47, 5, 6, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 9,
+ 10, 11, 12, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 18, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 47, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 56,
+ 47, 47, 14, 47, 47, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 57,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 3, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 13,
+ 47, 47, 14, 15, 16, 17, 18, 47,
+ 20, 47, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 58,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 22, 59, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 21,
+ 38, 21, 1, 1, 2, 3, 48, 48,
+ 47, 5, 6, 1, 1, 47, 47, 47,
+ 1, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 19, 20, 47, 1, 1, 60, 60,
+ 60, 60, 60, 60, 60, 1, 1, 60,
+ 60, 60, 1, 60, 0
+};
+
+static const char _myanmar_syllable_machine_trans_targs[] = {
+ 0, 1, 26, 37, 0, 27, 29, 51,
+ 54, 39, 40, 41, 28, 43, 44, 46,
+ 47, 48, 30, 50, 45, 0, 2, 13,
+ 0, 3, 5, 14, 15, 16, 4, 18,
+ 19, 21, 22, 23, 6, 25, 20, 12,
+ 9, 10, 11, 7, 8, 17, 24, 0,
+ 0, 36, 33, 34, 35, 31, 32, 38,
+ 42, 49, 52, 53, 0
+};
+
+static const char _myanmar_syllable_machine_trans_actions[] = {
+ 3, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7,
+ 8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9
+};
+
+static const char _myanmar_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const char _myanmar_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const short _myanmar_syllable_machine_eof_trans[] = {
+ 0, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 22, 22, 48, 61
+};
+
+static const int myanmar_syllable_machine_start = 0;
+static const int myanmar_syllable_machine_first_final = 0;
+static const int myanmar_syllable_machine_error = -1;
+
+static const int myanmar_syllable_machine_en_main = 0;
+
+
+#line 55 "hb-ot-shaper-myanmar-machine.rl"
+
+
+
+#line 117 "hb-ot-shaper-myanmar-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_myanmar (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 447 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ cs = myanmar_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 137 "hb-ot-shaper-myanmar-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 463 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 477 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
+ _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
+
+ _slen = _myanmar_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
+ ( info[p].myanmar_category()) <= _keys[1] ?
+ ( info[p].myanmar_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _myanmar_syllable_machine_trans_targs[_trans];
+
+ if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
+ case 6:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 4:
+#line 111 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 8:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 5:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 7:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 9:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+#line 523 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+_again:
+ switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 532 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 145 "hb-ot-shaper-myanmar-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_MYANMAR_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
index 13beaf4d4c..1ccafbca7e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
@@ -28,14 +28,16 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-myanmar.hh"
-#include "hb-ot-shape-complex-myanmar-machine.hh"
+#include "hb-ot-shaper-myanmar-machine.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-layout.hh"
/*
* Myanmar shaper.
*/
+
static const hb_tag_t
myanmar_basic_features[] =
{
@@ -62,6 +64,40 @@ myanmar_other_features[] =
HB_TAG('p','s','t','s'),
};
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.myanmar_category() = (myanmar_category_t) (type & 0xFFu);
+}
+
+
+static inline bool
+is_one_of_myanmar (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.myanmar_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_MYANMAR (FLAG (M_Cat(C)) | FLAG (M_Cat(CS)) | FLAG (M_Cat(Ra)) | /* FLAG (M_Cat(CM)) | */ FLAG (M_Cat(IV)) | FLAG (M_Cat(GB)) | FLAG (M_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant_myanmar (const hb_glyph_info_t &info)
+{
+ return is_one_of_myanmar (info, CONSONANT_FLAGS_MYANMAR);
+}
+
+
static void
setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
@@ -92,6 +128,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (nullptr);
}
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
@@ -118,6 +155,7 @@ setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_myanmar (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
@@ -129,7 +167,7 @@ compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
int a = pa->myanmar_position();
int b = pb->myanmar_position();
- return a < b ? -1 : a == b ? 0 : +1;
+ return (int) a - (int) b;
}
@@ -148,9 +186,9 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
{
unsigned int limit = start;
if (start + 3 <= end &&
- info[start ].myanmar_category() == OT_Ra &&
- info[start+1].myanmar_category() == OT_As &&
- info[start+2].myanmar_category() == OT_H)
+ info[start ].myanmar_category() == M_Cat(Ra) &&
+ info[start+1].myanmar_category() == M_Cat(As) &&
+ info[start+2].myanmar_category() == M_Cat(H))
{
limit += 3;
base = start;
@@ -162,7 +200,7 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
base = limit;
for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
+ if (is_consonant_myanmar (info[i]))
{
base = i;
break;
@@ -187,39 +225,40 @@ initial_reordering_consonant_syllable (hb_buffer_t *buffer,
* Myanmar reordering! */
for (; i < end; i++)
{
- if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */
+ if (info[i].myanmar_category() == M_Cat(MR)) /* Pre-base reordering */
{
info[i].myanmar_position() = POS_PRE_C;
continue;
}
- if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */
+ if (info[i].myanmar_category() == M_Cat(VPre)) /* Left matra */
{
+ info[i].myanmar_position() = POS_PRE_M;
continue;
}
- if (info[i].myanmar_category() == OT_VS)
+ if (info[i].myanmar_category() == M_Cat(VS))
{
info[i].myanmar_position() = info[i - 1].myanmar_position();
continue;
}
- if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw)
+ if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == M_Cat(VBlw))
{
pos = POS_BELOW_C;
info[i].myanmar_position() = pos;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(A))
{
info[i].myanmar_position() = POS_BEFORE_SUB;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(VBlw))
{
info[i].myanmar_position() = pos;
continue;
}
- if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
+ if (pos == POS_BELOW_C && info[i].myanmar_category() != M_Cat(A))
{
pos = POS_AFTER_SUB;
info[i].myanmar_position() = pos;
@@ -247,7 +286,6 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
initial_reordering_consonant_syllable (buffer, start, end);
break;
- case myanmar_punctuation_cluster:
case myanmar_non_myanmar_cluster:
break;
}
@@ -262,7 +300,7 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan,
{
hb_syllabic_insert_dotted_circles (font, buffer,
myanmar_broken_cluster,
- OT_GB);
+ M_Cat(DOTTEDCIRCLE));
foreach_syllable (buffer, start, end)
reorder_syllable_myanmar (plan, font->face, buffer, start, end);
@@ -274,7 +312,7 @@ reorder_myanmar (const hb_ot_shape_plan_t *plan,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
+const hb_ot_shaper_t _hb_ot_shaper_myanmar =
{
collect_features_myanmar,
nullptr, /* override_features */
@@ -296,7 +334,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
/* Ugly Zawgyi encoding.
* Disable all auto processing.
* https://github.com/harfbuzz/harfbuzz/issues/1162 */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
+const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi =
{
nullptr, /* collect_features */
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
index 76092c7f38..a8e0d8e8c1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
@@ -26,7 +26,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-syllabic.hh"
+#include "hb-ot-shaper-syllabic.hh"
void
@@ -39,31 +39,18 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == broken_syllable_type)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
+ if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
return;
-
hb_codepoint_t dottedcircle_glyph;
if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
return;
hb_glyph_info_t dottedcircle = {0};
dottedcircle.codepoint = 0x25CCu;
- dottedcircle.complex_var_u8_category() = dottedcircle_category;
+ dottedcircle.ot_shaper_var_u8_category() = dottedcircle_category;
if (dottedcircle_position != -1)
- dottedcircle.complex_var_u8_auxiliary() = dottedcircle_position;
+ dottedcircle.ot_shaper_var_u8_auxiliary() = dottedcircle_position;
dottedcircle.codepoint = dottedcircle_glyph;
buffer->clear_output ();
@@ -87,7 +74,7 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
{
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
- buffer->cur().complex_var_u8_category() == (unsigned) repha_category)
+ buffer->cur().ot_shaper_var_u8_category() == (unsigned) repha_category)
(void) buffer->next_glyph ();
}
@@ -99,5 +86,13 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
buffer->sync ();
}
+HB_INTERNAL void
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+}
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
index b901a660d3..e8a15bb48a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
@@ -22,12 +22,12 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-#ifndef HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
-#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
+#ifndef HB_OT_SHAPER_SYLLABIC_HH
+#define HB_OT_SHAPER_SYLLABIC_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
HB_INTERNAL void
@@ -38,5 +38,10 @@ hb_syllabic_insert_dotted_circles (hb_font_t *font,
int repha_category = -1,
int dottedcircle_position = -1);
+HB_INTERNAL void
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
-#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */
+#endif /* HB_OT_SHAPER_SYLLABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
index a1e27a83be..1280e7ed17 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
@@ -28,7 +28,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
/* Thai / Lao shaper */
@@ -222,7 +222,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
+#ifdef HB_NO_OT_SHAPER_THAI_FALLBACK
return;
#endif
@@ -279,7 +279,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
* to be what Uniscribe and other engines implement. According to Eric Muller:
*
* When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the
- * NIKHAHIT backwards over any tone mark (0E48-0E4B).
+ * NIKHAHIT backwards over any above-base marks.
*
* <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
*
@@ -308,8 +308,8 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
* Nikhahit: U+0E4D U+0ECD
*
* Testing shows that Uniscribe reorder the following marks:
- * Thai: <0E31,0E34..0E37,0E47..0E4E>
- * Lao: <0EB1,0EB4..0EB7,0EC7..0ECE>
+ * Thai: <0E31,0E34..0E37, 0E47..0E4E>
+ * Lao: <0EB1,0EB4..0EB7,0EBB,0EC8..0ECD>
*
* Note how the Lao versions are the same as Thai + 0x80.
*/
@@ -319,7 +319,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
-#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
+#define IS_ABOVE_BASE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u, 0x0E3Bu, 0x0E3Bu))
buffer->clear_output ();
unsigned int count = buffer->len;
@@ -343,7 +343,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
/* Ok, let's see... */
unsigned int start = end - 2;
- while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
+ while (start > 0 && IS_ABOVE_BASE_MARK (buffer->out_info[start - 1].codepoint))
start--;
if (start + 2 < end)
@@ -371,7 +371,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan,
do_thai_pua_shaping (plan, buffer, font);
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
+const hb_ot_shaper_t _hb_ot_shaper_thai =
{
nullptr, /* collect_features */
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
new file mode 100644
index 0000000000..65e65ff39d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
@@ -0,0 +1,931 @@
+
+#line 1 "hb-ot-shaper-use-machine.rl"
+/*
+ * Copyright © 2015 Mozilla Foundation.
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_USE_MACHINE_HH
+#define HB_OT_SHAPER_USE_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-syllabic.hh"
+
+/* buffer var allocations */
+#define use_category() ot_shaper_var_u8_category()
+
+#define USE(Cat) use_syllable_machine_ex_##Cat
+
+enum use_syllable_type_t {
+ use_virama_terminated_cluster,
+ use_sakot_terminated_cluster,
+ use_standard_cluster,
+ use_number_joiner_terminated_cluster,
+ use_numeral_cluster,
+ use_symbol_cluster,
+ use_hieroglyph_cluster,
+ use_broken_cluster,
+ use_non_cluster,
+};
+
+
+#line 57 "hb-ot-shaper-use-machine.hh"
+#define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CGJ 6u
+#define use_syllable_machine_ex_CMAbv 31u
+#define use_syllable_machine_ex_CMBlw 32u
+#define use_syllable_machine_ex_CS 43u
+#define use_syllable_machine_ex_FAbv 24u
+#define use_syllable_machine_ex_FBlw 25u
+#define use_syllable_machine_ex_FMAbv 45u
+#define use_syllable_machine_ex_FMBlw 46u
+#define use_syllable_machine_ex_FMPst 47u
+#define use_syllable_machine_ex_FPst 26u
+#define use_syllable_machine_ex_G 49u
+#define use_syllable_machine_ex_GB 5u
+#define use_syllable_machine_ex_H 12u
+#define use_syllable_machine_ex_HN 13u
+#define use_syllable_machine_ex_HVM 53u
+#define use_syllable_machine_ex_IS 44u
+#define use_syllable_machine_ex_J 50u
+#define use_syllable_machine_ex_MAbv 27u
+#define use_syllable_machine_ex_MBlw 28u
+#define use_syllable_machine_ex_MPre 30u
+#define use_syllable_machine_ex_MPst 29u
+#define use_syllable_machine_ex_N 4u
+#define use_syllable_machine_ex_O 0u
+#define use_syllable_machine_ex_R 18u
+#define use_syllable_machine_ex_SB 51u
+#define use_syllable_machine_ex_SE 52u
+#define use_syllable_machine_ex_SMAbv 41u
+#define use_syllable_machine_ex_SMBlw 42u
+#define use_syllable_machine_ex_SUB 11u
+#define use_syllable_machine_ex_Sk 48u
+#define use_syllable_machine_ex_VAbv 33u
+#define use_syllable_machine_ex_VBlw 34u
+#define use_syllable_machine_ex_VMAbv 37u
+#define use_syllable_machine_ex_VMBlw 38u
+#define use_syllable_machine_ex_VMPre 23u
+#define use_syllable_machine_ex_VMPst 39u
+#define use_syllable_machine_ex_VPre 22u
+#define use_syllable_machine_ex_VPst 35u
+#define use_syllable_machine_ex_WJ 16u
+#define use_syllable_machine_ex_ZWNJ 14u
+
+
+#line 101 "hb-ot-shaper-use-machine.hh"
+static const unsigned char _use_syllable_machine_trans_keys[] = {
+ 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
+ 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 53u,
+ 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u, 12u, 53u,
+ 11u, 53u, 1u, 1u, 1u, 48u, 11u, 53u, 41u, 42u, 42u, 42u, 11u, 53u, 11u, 53u,
+ 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u,
+ 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u,
+ 13u, 13u, 4u, 4u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u,
+ 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u,
+ 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u,
+ 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u,
+ 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
+ 1u, 1u, 24u, 48u, 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u,
+ 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u, 4u, 4u, 13u, 13u,
+ 1u, 53u, 11u, 53u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
+ 0
+};
+
+static const char _use_syllable_machine_key_spans[] = {
+ 54, 43, 43, 53, 26, 24, 23, 22,
+ 2, 1, 25, 25, 25, 1, 25, 32,
+ 31, 31, 31, 42, 31, 42, 42, 42,
+ 43, 1, 48, 43, 2, 1, 43, 43,
+ 53, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 32, 31, 31, 31,
+ 42, 31, 42, 42, 42, 43, 1, 48,
+ 1, 1, 43, 43, 53, 26, 24, 23,
+ 22, 2, 1, 25, 25, 25, 1, 25,
+ 32, 31, 31, 31, 42, 31, 42, 42,
+ 42, 43, 1, 48, 43, 43, 53, 26,
+ 24, 23, 22, 2, 1, 25, 25, 25,
+ 1, 25, 32, 31, 31, 31, 42, 31,
+ 42, 42, 42, 43, 1, 48, 1, 1,
+ 53, 43, 2, 1, 5, 3, 4, 3
+};
+
+static const short _use_syllable_machine_index_offsets[] = {
+ 0, 55, 99, 143, 197, 224, 249, 273,
+ 296, 299, 301, 327, 353, 379, 381, 407,
+ 440, 472, 504, 536, 579, 611, 654, 697,
+ 740, 784, 786, 835, 879, 882, 884, 928,
+ 972, 1026, 1053, 1078, 1102, 1125, 1128, 1130,
+ 1156, 1182, 1208, 1210, 1236, 1269, 1301, 1333,
+ 1365, 1408, 1440, 1483, 1526, 1569, 1613, 1615,
+ 1664, 1666, 1668, 1712, 1756, 1810, 1837, 1862,
+ 1886, 1909, 1912, 1914, 1940, 1966, 1992, 1994,
+ 2020, 2053, 2085, 2117, 2149, 2192, 2224, 2267,
+ 2310, 2353, 2397, 2399, 2448, 2492, 2536, 2590,
+ 2617, 2642, 2666, 2689, 2692, 2694, 2720, 2746,
+ 2772, 2774, 2800, 2833, 2865, 2897, 2929, 2972,
+ 3004, 3047, 3090, 3133, 3177, 3179, 3228, 3230,
+ 3232, 3286, 3330, 3333, 3335, 3341, 3345, 3350
+};
+
+static const unsigned char _use_syllable_machine_indicies[] = {
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 2, 2,
+ 2, 2, 8, 2, 2, 2, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 2, 23, 24, 25,
+ 2, 26, 27, 28, 29, 30, 31, 32,
+ 29, 33, 2, 34, 2, 35, 2, 37,
+ 38, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52,
+ 36, 53, 54, 55, 36, 56, 57, 36,
+ 58, 59, 60, 61, 58, 36, 36, 36,
+ 36, 62, 36, 37, 38, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 49,
+ 49, 50, 51, 52, 36, 53, 54, 55,
+ 36, 36, 36, 36, 58, 59, 60, 61,
+ 58, 36, 36, 36, 36, 62, 36, 37,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 40, 41, 42,
+ 43, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 53, 54, 55, 36, 36,
+ 36, 36, 36, 59, 60, 61, 63, 36,
+ 36, 36, 36, 40, 36, 40, 41, 42,
+ 43, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 53, 54, 55, 36, 36,
+ 36, 36, 36, 59, 60, 61, 63, 36,
+ 41, 42, 43, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 59, 60, 61,
+ 36, 42, 43, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 59, 60, 61,
+ 36, 43, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 59, 60, 61, 36,
+ 59, 60, 36, 60, 36, 41, 42, 43,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 53, 54, 55, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 41,
+ 42, 43, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 54, 55, 36,
+ 36, 36, 36, 36, 59, 60, 61, 63,
+ 36, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 64, 36, 41, 42, 43,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 39,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 65, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 39, 40, 41, 42, 43, 36,
+ 45, 46, 36, 36, 36, 50, 51, 52,
+ 36, 53, 54, 55, 36, 36, 36, 36,
+ 36, 59, 60, 61, 63, 36, 36, 36,
+ 36, 40, 36, 40, 41, 42, 43, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 53, 54, 55, 36, 36, 36, 36,
+ 36, 59, 60, 61, 63, 36, 36, 36,
+ 36, 40, 36, 65, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 39, 40, 41,
+ 42, 43, 36, 36, 46, 36, 36, 36,
+ 50, 51, 52, 36, 53, 54, 55, 36,
+ 36, 36, 36, 36, 59, 60, 61, 63,
+ 36, 36, 36, 36, 40, 36, 65, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 39, 40, 41, 42, 43, 36, 36, 36,
+ 36, 36, 36, 50, 51, 52, 36, 53,
+ 54, 55, 36, 36, 36, 36, 36, 59,
+ 60, 61, 63, 36, 36, 36, 36, 40,
+ 36, 65, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 39, 40, 41, 42, 43,
+ 44, 45, 46, 36, 36, 36, 50, 51,
+ 52, 36, 53, 54, 55, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 36,
+ 36, 36, 40, 36, 37, 38, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 36, 49, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 58, 59, 60,
+ 61, 58, 36, 36, 36, 36, 62, 36,
+ 37, 36, 37, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 37, 38, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 36, 53, 54, 55,
+ 36, 36, 36, 36, 58, 59, 60, 61,
+ 58, 36, 36, 36, 36, 62, 36, 56,
+ 57, 36, 57, 36, 67, 68, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77,
+ 1, 78, 79, 80, 81, 66, 82, 83,
+ 84, 66, 66, 66, 66, 85, 86, 87,
+ 88, 89, 66, 66, 66, 66, 90, 66,
+ 67, 68, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 78, 79, 80,
+ 81, 66, 82, 83, 84, 66, 66, 66,
+ 66, 85, 86, 87, 88, 89, 66, 66,
+ 66, 66, 90, 66, 67, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 70, 71, 72, 73, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 82, 83, 84, 66, 66, 66, 66, 66,
+ 86, 87, 88, 91, 66, 66, 66, 66,
+ 70, 66, 70, 71, 72, 73, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 82, 83, 84, 66, 66, 66, 66, 66,
+ 86, 87, 88, 91, 66, 71, 72, 73,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 86, 87, 88, 66, 72, 73,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 86, 87, 88, 66, 73, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 86, 87, 88, 66, 86, 87, 66,
+ 87, 66, 71, 72, 73, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 82,
+ 83, 84, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 71, 72, 73, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 83, 84, 66, 66, 66, 66,
+ 66, 86, 87, 88, 91, 66, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 93, 92, 71, 72, 73, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 69, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 94, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 69,
+ 70, 71, 72, 73, 66, 75, 76, 66,
+ 66, 66, 79, 80, 81, 66, 82, 83,
+ 84, 66, 66, 66, 66, 66, 86, 87,
+ 88, 91, 66, 66, 66, 66, 70, 66,
+ 70, 71, 72, 73, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 82, 83,
+ 84, 66, 66, 66, 66, 66, 86, 87,
+ 88, 91, 66, 66, 66, 66, 70, 66,
+ 94, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 69, 70, 71, 72, 73, 66,
+ 66, 76, 66, 66, 66, 79, 80, 81,
+ 66, 82, 83, 84, 66, 66, 66, 66,
+ 66, 86, 87, 88, 91, 66, 66, 66,
+ 66, 70, 66, 94, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 69, 70, 71,
+ 72, 73, 66, 66, 66, 66, 66, 66,
+ 79, 80, 81, 66, 82, 83, 84, 66,
+ 66, 66, 66, 66, 86, 87, 88, 91,
+ 66, 66, 66, 66, 70, 66, 94, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 69, 70, 71, 72, 73, 74, 75, 76,
+ 66, 66, 66, 79, 80, 81, 66, 82,
+ 83, 84, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 66, 66, 66, 70,
+ 66, 67, 68, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 66, 78, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 85, 86, 87, 88, 89, 66,
+ 66, 66, 66, 90, 66, 67, 95, 67,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 97, 96, 3, 98, 99, 100, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 66, 115, 116,
+ 117, 66, 56, 57, 66, 118, 119, 120,
+ 88, 121, 66, 66, 66, 66, 122, 66,
+ 99, 100, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 111, 111, 112, 113,
+ 114, 66, 115, 116, 117, 66, 66, 66,
+ 66, 118, 119, 120, 88, 121, 66, 66,
+ 66, 66, 122, 66, 99, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 102, 103, 104, 105, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 115, 116, 117, 66, 66, 66, 66, 66,
+ 119, 120, 88, 123, 66, 66, 66, 66,
+ 102, 66, 102, 103, 104, 105, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 115, 116, 117, 66, 66, 66, 66, 66,
+ 119, 120, 88, 123, 66, 103, 104, 105,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 119, 120, 88, 66, 104, 105,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 119, 120, 88, 66, 105, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 119, 120, 88, 66, 119, 120, 66,
+ 120, 66, 103, 104, 105, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 115,
+ 116, 117, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 103, 104, 105, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 116, 117, 66, 66, 66, 66,
+ 66, 119, 120, 88, 123, 66, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 124, 92, 103, 104, 105, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 101, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 125, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 101,
+ 102, 103, 104, 105, 66, 107, 108, 66,
+ 66, 66, 112, 113, 114, 66, 115, 116,
+ 117, 66, 66, 66, 66, 66, 119, 120,
+ 88, 123, 66, 66, 66, 66, 102, 66,
+ 102, 103, 104, 105, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 115, 116,
+ 117, 66, 66, 66, 66, 66, 119, 120,
+ 88, 123, 66, 66, 66, 66, 102, 66,
+ 125, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 101, 102, 103, 104, 105, 66,
+ 66, 108, 66, 66, 66, 112, 113, 114,
+ 66, 115, 116, 117, 66, 66, 66, 66,
+ 66, 119, 120, 88, 123, 66, 66, 66,
+ 66, 102, 66, 125, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 101, 102, 103,
+ 104, 105, 66, 66, 66, 66, 66, 66,
+ 112, 113, 114, 66, 115, 116, 117, 66,
+ 66, 66, 66, 66, 119, 120, 88, 123,
+ 66, 66, 66, 66, 102, 66, 125, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 101, 102, 103, 104, 105, 106, 107, 108,
+ 66, 66, 66, 112, 113, 114, 66, 115,
+ 116, 117, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 66, 66, 66, 102,
+ 66, 99, 100, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 66, 111, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 118, 119, 120, 88, 121, 66,
+ 66, 66, 66, 122, 66, 99, 95, 99,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 99, 100, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 66, 115, 116, 117, 66, 66, 66,
+ 66, 118, 119, 120, 88, 121, 66, 66,
+ 66, 66, 122, 66, 5, 6, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 19, 19, 20, 21, 22, 126, 23, 24,
+ 25, 126, 126, 126, 126, 29, 30, 31,
+ 32, 29, 126, 126, 126, 126, 35, 126,
+ 5, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 10, 11,
+ 12, 13, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 23, 24, 25, 126,
+ 126, 126, 126, 126, 30, 31, 32, 127,
+ 126, 126, 126, 126, 10, 126, 10, 11,
+ 12, 13, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 23, 24, 25, 126,
+ 126, 126, 126, 126, 30, 31, 32, 127,
+ 126, 11, 12, 13, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 30, 31,
+ 32, 126, 12, 13, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 30, 31,
+ 32, 126, 13, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 126, 30, 31, 126, 31, 126, 11, 12,
+ 13, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 23, 24, 25, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 11, 12, 13, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 24, 25,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 127, 126, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 128, 126, 11, 12,
+ 13, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 9, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 129, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 9, 10, 11, 12, 13,
+ 126, 15, 16, 126, 126, 126, 20, 21,
+ 22, 126, 23, 24, 25, 126, 126, 126,
+ 126, 126, 30, 31, 32, 127, 126, 126,
+ 126, 126, 10, 126, 10, 11, 12, 13,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 23, 24, 25, 126, 126, 126,
+ 126, 126, 30, 31, 32, 127, 126, 126,
+ 126, 126, 10, 126, 129, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 9, 10,
+ 11, 12, 13, 126, 126, 16, 126, 126,
+ 126, 20, 21, 22, 126, 23, 24, 25,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 127, 126, 126, 126, 126, 10, 126, 129,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 9, 10, 11, 12, 13, 126, 126,
+ 126, 126, 126, 126, 20, 21, 22, 126,
+ 23, 24, 25, 126, 126, 126, 126, 126,
+ 30, 31, 32, 127, 126, 126, 126, 126,
+ 10, 126, 129, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 9, 10, 11, 12,
+ 13, 14, 15, 16, 126, 126, 126, 20,
+ 21, 22, 126, 23, 24, 25, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 126, 126, 126, 10, 126, 5, 6, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 126, 19, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 29, 30,
+ 31, 32, 29, 126, 126, 126, 126, 35,
+ 126, 5, 126, 5, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 130, 126, 7, 126,
+ 1, 126, 126, 126, 1, 126, 126, 126,
+ 126, 126, 5, 6, 7, 126, 126, 126,
+ 126, 126, 126, 126, 126, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 126, 23, 24, 25, 126,
+ 26, 27, 126, 29, 30, 31, 32, 29,
+ 126, 126, 126, 126, 35, 126, 5, 6,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 126,
+ 23, 24, 25, 126, 126, 126, 126, 29,
+ 30, 31, 32, 29, 126, 126, 126, 126,
+ 35, 126, 26, 27, 126, 27, 126, 1,
+ 131, 131, 131, 1, 131, 133, 132, 33,
+ 132, 33, 133, 132, 133, 132, 33, 132,
+ 34, 132, 0
+};
+
+static const char _use_syllable_machine_trans_targs[] = {
+ 1, 30, 0, 56, 58, 85, 86, 110,
+ 112, 98, 87, 88, 89, 90, 102, 104,
+ 105, 106, 113, 107, 99, 100, 101, 93,
+ 94, 95, 114, 115, 116, 108, 91, 92,
+ 0, 117, 119, 109, 0, 2, 3, 15,
+ 4, 5, 6, 7, 19, 21, 22, 23,
+ 27, 24, 16, 17, 18, 10, 11, 12,
+ 28, 29, 25, 8, 9, 0, 26, 13,
+ 14, 20, 0, 31, 32, 44, 33, 34,
+ 35, 36, 48, 50, 51, 52, 53, 45,
+ 46, 47, 39, 40, 41, 54, 37, 38,
+ 0, 54, 55, 42, 0, 43, 49, 0,
+ 0, 57, 0, 59, 60, 72, 61, 62,
+ 63, 64, 76, 78, 79, 80, 84, 81,
+ 73, 74, 75, 67, 68, 69, 82, 65,
+ 66, 82, 83, 70, 71, 77, 0, 96,
+ 97, 103, 111, 0, 0, 118
+};
+
+static const char _use_syllable_machine_trans_actions[] = {
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 0, 7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 0,
+ 9, 10, 0, 0, 11, 0, 0, 12,
+ 13, 0, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 8, 0,
+ 0, 10, 0, 0, 0, 0, 15, 0,
+ 0, 0, 0, 16, 17, 0
+};
+
+static const char _use_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const char _use_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const short _use_syllable_machine_eof_trans[] = {
+ 0, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 93, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 96, 67,
+ 97, 99, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 93, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 96, 67, 67, 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, 132, 133, 133, 133
+};
+
+static const int use_syllable_machine_start = 0;
+static const int use_syllable_machine_first_final = 0;
+static const int use_syllable_machine_error = -1;
+
+static const int use_syllable_machine_en_main = 0;
+
+
+#line 58 "hb-ot-shaper-use-machine.rl"
+
+
+
+#line 182 "hb-ot-shaper-use-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+
+template <typename Iter>
+struct machine_index_t :
+ hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t>
+{
+ machine_index_t (const Iter& it) : it (it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it), is_null (o.is_null) {}
+
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+
+ typename Iter::item_t __item__ () const { return *it; }
+ typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+
+ void operator = (unsigned n)
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
+ bool operator != (const machine_index_t& o) const { return !(*this == o); }
+
+ private:
+ Iter it;
+ bool is_null = false;
+};
+struct
+{
+ template <typename Iter,
+ hb_requires (hb_is_iterable (Iter))>
+ machine_index_t<hb_iter_type<Iter>>
+ operator () (Iter&& it) const
+ { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
+}
+HB_FUNCOBJ (machine_index);
+
+
+
+static bool
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return i.use_category() != USE(CGJ); }
+
+static inline void
+find_syllables_use (hb_buffer_t *buffer)
+{
+ hb_glyph_info_t *info = buffer->info;
+ auto p =
+ + hb_iter (info, buffer->len)
+ | hb_enumerate
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
+ hb_second)
+ | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
+ {
+ if (p.second.use_category() == USE(ZWNJ))
+ for (unsigned i = p.first + 1; i < buffer->len; ++i)
+ if (not_ccs_default_ignorable (info[i]))
+ return !_hb_glyph_info_is_unicode_mark (&info[i]);
+ return true;
+ })
+ | hb_enumerate
+ | machine_index
+ ;
+ auto pe = p + p.len ();
+ auto eof = +pe;
+ auto ts = +p;
+ auto te = +p;
+ unsigned int act HB_UNUSED;
+ int cs;
+
+#line 784 "hb-ot-shaper-use-machine.hh"
+ {
+ cs = use_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 282 "hb-ot-shaper-use-machine.rl"
+
+
+ unsigned int syllable_serial = 1;
+
+#line 797 "hb-ot-shaper-use-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _use_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 811 "hb-ot-shaper-use-machine.hh"
+ }
+
+ _keys = _use_syllable_machine_trans_keys + (cs<<1);
+ _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
+
+ _slen = _use_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
+ ( (*p).second.second.use_category()) <= _keys[1] ?
+ ( (*p).second.second.use_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _use_syllable_machine_trans_targs[_trans];
+
+ if ( _use_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _use_syllable_machine_trans_actions[_trans] ) {
+ case 9:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 6:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 4:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_non_cluster); }}
+ break;
+ case 11:
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
+ break;
+ case 7:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 14:
+#line 173 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
+ break;
+ case 13:
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_numeral_cluster); }}
+ break;
+ case 5:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 17:
+#line 176 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
+ break;
+ case 15:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 16:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_non_cluster); }}
+ break;
+ case 12:
+#line 1 "NONE"
+ { switch( act ) {
+ case 1:
+ {{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
+ break;
+ case 2:
+ {{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
+ break;
+ }
+ }
+ break;
+ case 8:
+#line 1 "NONE"
+ {te = p+1;}
+#line 170 "hb-ot-shaper-use-machine.rl"
+ {act = 1;}
+ break;
+ case 10:
+#line 1 "NONE"
+ {te = p+1;}
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {act = 2;}
+ break;
+#line 901 "hb-ot-shaper-use-machine.hh"
+ }
+
+_again:
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 910 "hb-ot-shaper-use-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _use_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 287 "hb-ot-shaper-use-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_USE_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
index c8e5151694..5aa025fb4c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
@@ -37,12 +37,12 @@
* UnicodeData.txt does not have a header.
*/
-#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
+#ifndef HB_OT_SHAPER_USE_TABLE_HH
+#define HB_OT_SHAPER_USE_TABLE_HH
#include "hb.hh"
-#include "hb-ot-shape-complex-use-machine.hh"
+#include "hb-ot-shaper-use-machine.hh"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
@@ -53,6 +53,7 @@
#define GB USE(GB) /* BASE_OTHER */
#define H USE(H) /* HALANT */
#define HN USE(HN) /* HALANT_NUM */
+#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
#define IS USE(IS) /* INVISIBLE_STACKER */
#define J USE(J) /* HIEROGLYPH_JOINER */
#define N USE(N) /* BASE_NUM */
@@ -246,7 +247,7 @@ static const uint8_t use_table[] = {
/* 0D90 */ B, B, B, B, B, B, B, WJ, WJ, WJ, B, B, B, B, B, B,
/* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
/* 0DB0 */ B, B, WJ, B, B, B, B, B, B, B, B, B, WJ, B, WJ, WJ,
- /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, H, WJ, WJ, WJ, WJ, VPst,
+ /* 0DC0 */ B, B, B, B, B, B, B, WJ, WJ, WJ, HVM, WJ, WJ, WJ, WJ, VPst,
/* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, WJ, VBlw, WJ, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
/* 0DE0 */ WJ, WJ, WJ, WJ, WJ, WJ, B, B, B, B, B, B, B, B, B, B,
/* 0DF0 */ WJ, WJ, VPst, VPst, O, WJ, WJ, WJ,
@@ -1531,6 +1532,7 @@ hb_use_get_category (hb_glyph_info_t info)
#undef GB
#undef H
#undef HN
+#undef HVM
#undef IS
#undef J
#undef N
@@ -1566,5 +1568,5 @@ hb_use_get_category (hb_glyph_info_t info)
#undef VMPre
-#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
+#endif /* HB_OT_SHAPER_USE_TABLE_HH */
/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
index 1d13c8a126..60394ed4d8 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
@@ -30,11 +30,11 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-use-machine.hh"
-#include "hb-ot-shape-complex-use-table.hh"
-#include "hb-ot-shape-complex-arabic.hh"
-#include "hb-ot-shape-complex-arabic-joining-list.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-use-machine.hh"
+#include "hb-ot-shaper-use-table.hh"
+#include "hb-ot-shaper-arabic.hh"
+#include "hb-ot-shaper-arabic-joining-list.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
/*
@@ -133,6 +133,7 @@ collect_features_use (hb_ot_shape_planner_t *plan)
map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
map->add_gsub_pause (reorder_use);
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
/* "Topographical features" */
for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
@@ -297,6 +298,7 @@ setup_syllables_use (const hb_ot_shape_plan_t *plan,
hb_font_t *font HB_UNUSED,
hb_buffer_t *buffer)
{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
find_syllables_use (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
@@ -349,7 +351,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
static inline bool
is_halant_use (const hb_glyph_info_t &info)
{
- return (info.use_category() == USE(H) || info.use_category() == USE(IS)) &&
+ return (info.use_category() == USE(H) || info.use_category() == USE(HVM) || info.use_category() == USE(IS)) &&
!_hb_glyph_info_ligated (&info);
}
@@ -480,7 +482,7 @@ compose_use (const hb_ot_shape_normalize_context_t *c,
}
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
+const hb_ot_shaper_t _hb_ot_shaper_use =
{
collect_features_use,
nullptr, /* override_features */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc
index d2cca105a4..be4ac813b1 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc
@@ -18,7 +18,7 @@
#ifndef HB_NO_OT_SHAPE
-#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
static void
_output_dotted_circle (hb_buffer_t *buffer)
@@ -39,7 +39,7 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
hb_font_t *font HB_UNUSED)
{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#ifdef HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
return;
#endif
if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh
index d9082d4ead..5a7ee1b0f2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh
@@ -24,16 +24,16 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
-#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+#ifndef HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
#include "hb.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
HB_INTERNAL void
_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font);
-#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
+#endif /* HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
index 8012a9ae94..b823bf003c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
@@ -24,8 +24,8 @@
* Google Author(s): Behdad Esfahbod
*/
-#ifndef HB_OT_SHAPE_COMPLEX_HH
-#define HB_OT_SHAPE_COMPLEX_HH
+#ifndef HB_OT_SHAPER_HH
+#define HB_OT_SHAPER_HH
#include "hb.hh"
@@ -34,12 +34,12 @@
#include "hb-ot-shape-normalize.hh"
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_category() var2.u8[2]
-#define complex_var_u8_auxiliary() var2.u8[3]
+/* buffer var allocations, used by all OT shapers */
+#define ot_shaper_var_u8_category() var2.u8[2]
+#define ot_shaper_var_u8_auxiliary() var2.u8[3]
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+#define HB_OT_SHAPE_MAX_COMBINING_MARKS 32
enum hb_ot_shape_zero_width_marks_type_t {
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
@@ -49,22 +49,22 @@ enum hb_ot_shape_zero_width_marks_type_t {
/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
- HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (default) \
- HB_COMPLEX_SHAPER_IMPLEMENT (dumber) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
- HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
- HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
- HB_COMPLEX_SHAPER_IMPLEMENT (use) \
+#define HB_OT_SHAPERS_IMPLEMENT_SHAPERS \
+ HB_OT_SHAPER_IMPLEMENT (arabic) \
+ HB_OT_SHAPER_IMPLEMENT (default) \
+ HB_OT_SHAPER_IMPLEMENT (dumber) \
+ HB_OT_SHAPER_IMPLEMENT (hangul) \
+ HB_OT_SHAPER_IMPLEMENT (hebrew) \
+ HB_OT_SHAPER_IMPLEMENT (indic) \
+ HB_OT_SHAPER_IMPLEMENT (khmer) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+ HB_OT_SHAPER_IMPLEMENT (thai) \
+ HB_OT_SHAPER_IMPLEMENT (use) \
/* ^--- Add new shapers here; keep sorted. */
-struct hb_ot_complex_shaper_t
+struct hb_ot_shaper_t
{
/* collect_features()
* Called during shape_plan().
@@ -168,18 +168,18 @@ struct hb_ot_complex_shaper_t
bool fallback_position;
};
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
+#define HB_OT_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_shaper_t _hb_ot_shaper_##name;
+HB_OT_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_OT_SHAPER_IMPLEMENT
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
+static inline const hb_ot_shaper_t *
+hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
{
switch ((hb_tag_t) planner->props.script)
{
default:
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
/* Unicode-1.1 additions */
@@ -195,28 +195,28 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
planner->props.script == HB_SCRIPT_ARABIC) &&
HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
- return &_hb_ot_complex_shaper_arabic;
+ return &_hb_ot_shaper_arabic;
else
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
/* Unicode-1.1 additions */
case HB_SCRIPT_THAI:
case HB_SCRIPT_LAO:
- return &_hb_ot_complex_shaper_thai;
+ return &_hb_ot_shaper_thai;
/* Unicode-1.1 additions */
case HB_SCRIPT_HANGUL:
- return &_hb_ot_complex_shaper_hangul;
+ return &_hb_ot_shaper_hangul;
/* Unicode-1.1 additions */
case HB_SCRIPT_HEBREW:
- return &_hb_ot_complex_shaper_hebrew;
+ return &_hb_ot_shaper_hebrew;
/* Unicode-1.1 additions */
@@ -230,9 +230,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
case HB_SCRIPT_TAMIL:
case HB_SCRIPT_TELUGU:
- /* Unicode-3.0 additions */
- case HB_SCRIPT_SINHALA:
-
/* If the designer designed the font for the 'DFLT' script,
* (or we ended up arbitrarily pick 'latn'), use the default shaper.
* Otherwise, use the specific shaper.
@@ -240,14 +237,14 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
* If it's indy3 tag, send to USE. */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
- return &_hb_ot_complex_shaper_use;
+ return &_hb_ot_shaper_use;
else
- return &_hb_ot_complex_shaper_indic;
+ return &_hb_ot_shaper_indic;
case HB_SCRIPT_KHMER:
- return &_hb_ot_complex_shaper_khmer;
+ return &_hb_ot_shaper_khmer;
case HB_SCRIPT_MYANMAR:
/* If the designer designed the font for the 'DFLT' script,
@@ -260,16 +257,16 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else
- return &_hb_ot_complex_shaper_myanmar;
+ return &_hb_ot_shaper_myanmar;
#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
case HB_SCRIPT_MYANMAR_ZAWGYI:
/* https://github.com/harfbuzz/harfbuzz/issues/1162 */
- return &_hb_ot_complex_shaper_myanmar_zawgyi;
+ return &_hb_ot_shaper_myanmar_zawgyi;
/* Unicode-2.0 additions */
@@ -277,7 +274,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
/* Unicode-3.0 additions */
case HB_SCRIPT_MONGOLIAN:
- //case HB_SCRIPT_SINHALA:
+ case HB_SCRIPT_SINHALA:
/* Unicode-3.2 additions */
case HB_SCRIPT_BUHID:
@@ -390,11 +387,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
* GSUB/GPOS needed, so there may be no scripts found! */
if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
+ return &_hb_ot_shaper_default;
else
- return &_hb_ot_complex_shaper_use;
+ return &_hb_ot_shaper_use;
}
}
-#endif /* HB_OT_SHAPE_COMPLEX_HH */
+#endif /* HB_OT_SHAPER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
index b242fba2d8..9394b90ee6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
@@ -219,6 +219,7 @@ static const LangTag ot_languages2[] = {
{HB_TAG('z','u',' ',' '), HB_TAG('Z','U','L',' ')}, /* Zulu */
};
+#ifndef HB_NO_LANGUAGE_LONG
static const LangTag ot_languages3[] = {
{HB_TAG('a','a','e',' '), HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
{HB_TAG('a','a','o',' '), HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
@@ -1621,6 +1622,7 @@ static const LangTag ot_languages3[] = {
/*{HB_TAG('z','z','a',' '), HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
{HB_TAG('z','z','j',' '), HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
};
+#endif
/**
* hb_ot_tags_from_complex_language:
@@ -1636,7 +1638,7 @@ static const LangTag ot_languages3[] = {
*
* Return value: Whether any language systems were retrieved.
**/
-static bool
+static inline bool
hb_ot_tags_from_complex_language (const char *lang_str,
const char *limit,
unsigned int *count /* IN/OUT */,
@@ -2818,7 +2820,7 @@ out:
* Return value: The #hb_language_t corresponding to the BCP 47 language tag,
* or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
**/
-static hb_language_t
+static inline hb_language_t
hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
{
switch (tag)
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc
index a4a9515362..ce5cdce98b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -263,15 +263,19 @@ hb_ot_tags_from_language (const char *lang_str,
unsigned int *count,
hb_tag_t *tags)
{
- const char *s;
+#ifndef HB_NO_LANGUAGE_LONG
/* Check for matches of multiple subtags. */
if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
return;
+#endif
/* Find a language matching in the first component. */
- s = strchr (lang_str, '-');
+#ifndef HB_NO_LANGUAGE_LONG
+ const char *s; s = strchr (lang_str, '-');
+#endif
{
+#ifndef HB_NO_LANGUAGE_LONG
if (s && limit - lang_str >= 6)
{
const char *extlang_end = strchr (s + 1, '-');
@@ -280,6 +284,7 @@ hb_ot_tags_from_language (const char *lang_str,
ISALPHA (s[1]))
lang_str = s + 1;
}
+#endif
const LangTag *ot_languages = nullptr;
unsigned ot_languages_len = 0;
const char *dash = strchr (lang_str, '-');
@@ -289,21 +294,23 @@ hb_ot_tags_from_language (const char *lang_str,
ot_languages = ot_languages2;
ot_languages_len = ARRAY_LENGTH (ot_languages2);
}
+#ifndef HB_NO_LANGUAGE_LONG
else if (first_len == 3)
{
ot_languages = ot_languages3;
ot_languages_len = ARRAY_LENGTH (ot_languages3);
}
+#endif
hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
- static unsigned last_tag_idx; /* Poor man's cache. */
- unsigned tag_idx = last_tag_idx;
+ static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */
+ unsigned tag_idx = last_tag_idx.get_relaxed ();
if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_tag, &tag_idx))
{
- last_tag_idx = tag_idx;
+ last_tag_idx.set_relaxed (tag_idx);
unsigned int i;
while (tag_idx != 0 &&
ot_languages[tag_idx].language == ot_languages[tag_idx - 1].language)
@@ -320,6 +327,7 @@ hb_ot_tags_from_language (const char *lang_str,
}
}
+#ifndef HB_NO_LANGUAGE_LONG
if (!s)
s = lang_str + strlen (lang_str);
if (s - lang_str == 3) {
@@ -328,6 +336,7 @@ hb_ot_tags_from_language (const char *lang_str,
*count = 1;
return;
}
+#endif
*count = 0;
}
@@ -472,11 +481,13 @@ hb_ot_tag_to_language (hb_tag_t tag)
if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
return nullptr;
+#ifndef HB_NO_LANGUAGE_LONG
{
hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
if (disambiguated_tag != HB_LANGUAGE_INVALID)
return disambiguated_tag;
}
+#endif
char buf[4];
for (i = 0; i < ARRAY_LENGTH (ot_languages2); i++)
@@ -485,12 +496,14 @@ hb_ot_tag_to_language (hb_tag_t tag)
hb_tag_to_string (ot_languages2[i].language, buf);
return hb_language_from_string (buf, 2);
}
+#ifndef HB_NO_LANGUAGE_LONG
for (i = 0; i < ARRAY_LENGTH (ot_languages3); i++)
if (ot_languages3[i].tag == tag)
{
hb_tag_to_string (ot_languages3[i].language, buf);
return hb_language_from_string (buf, 3);
}
+#endif
/* Return a custom language in the form of "x-hbot-AABBCCDD".
* If it's three letters long, also guess it's ISO 639-3 and lower-case and
@@ -596,6 +609,7 @@ test_langs_sorted ()
abort();
}
}
+#ifndef HB_NO_LANGUAGE_LONG
for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages3); i++)
{
int c = ot_languages3[i].cmp (&ot_languages3[i - 1]);
@@ -606,6 +620,7 @@ test_langs_sorted ()
abort();
}
}
+#endif
}
int
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
index e066558683..c5c476bc0e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -213,7 +213,7 @@ struct fvar
if (!axis_index) axis_index = &i;
*axis_index = HB_OT_VAR_NO_AXIS_INDEX;
auto axes = get_axes ();
- return axes.lfind (tag, axis_index) && (axes[*axis_index].get_axis_deprecated (info), true);
+ return axes.lfind (tag, axis_index) && ((void) axes[*axis_index].get_axis_deprecated (info), true);
}
#endif
bool
@@ -221,7 +221,7 @@ struct fvar
{
unsigned i;
auto axes = get_axes ();
- return axes.lfind (tag, &i) && (axes[i].get_axis_info (i, info), true);
+ return axes.lfind (tag, &i) && ((void) axes[i].get_axis_info (i, info), true);
}
int normalize_axis_value (unsigned int axis_index, float v) const
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index 3b2a38b9a6..bf1039d1d6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -45,9 +45,10 @@ struct contour_point_t
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
- uint8_t flag;
- float x, y;
- bool is_end_point;
+ float x = 0.f;
+ float y = 0.f;
+ uint8_t flag = 0;
+ bool is_end_point = false;
};
struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -55,16 +56,24 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void extend (const hb_array_t<contour_point_t> &a)
{
unsigned int old_len = length;
- resize (old_len + a.length);
- for (unsigned int i = 0; i < a.length; i++)
- (*this)[old_len + i] = a[i];
+ if (unlikely (!resize (old_len + a.length)))
+ return;
+ auto arrayZ = this->arrayZ + old_len;
+ unsigned count = a.length;
+ for (unsigned int i = 0; i < count; i++)
+ arrayZ[i] = a.arrayZ[i];
}
void transform (const float (&matrix)[4])
{
- for (unsigned int i = 0; i < length; i++)
+ if (matrix[0] == 1.f && matrix[1] == 0.f &&
+ matrix[2] == 0.f && matrix[3] == 1.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
{
- contour_point_t &p = (*this)[i];
+ contour_point_t &p = arrayZ[i];
float x_ = p.x * matrix[0] + p.y * matrix[2];
p.y = p.x * matrix[1] + p.y * matrix[3];
p.x = x_;
@@ -73,8 +82,12 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void translate (const contour_point_t& delta)
{
- for (unsigned int i = 0; i < length; i++)
- (*this)[i].translate (delta);
+ if (delta.x == 0.f && delta.y == 0.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
+ arrayZ[i].translate (delta);
}
};
@@ -89,7 +102,7 @@ struct TupleVariationHeader
const TupleVariationHeader &get_next (unsigned axis_count) const
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
- float calculate_scalar (const int *coords, unsigned int coord_count,
+ float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
const hb_array_t<const F2DOT14> shared_tuples) const
{
hb_array_t<const F2DOT14> peak_tuple;
@@ -208,7 +221,7 @@ struct GlyphVariationData
{
const HBUINT8 *base = &(var_data+var_data->data);
const HBUINT8 *p = base;
- if (!unpack_points (p, shared_indices, var_data_bytes)) return false;
+ if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
data_offset = p - base;
}
return true;
@@ -258,7 +271,7 @@ struct GlyphVariationData
static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<unsigned int> &points /* OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_point_flag_t
{
@@ -266,21 +279,21 @@ struct GlyphVariationData
POINT_RUN_COUNT_MASK = 0x7F
};
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint16_t count = *p++;
if (count & POINTS_ARE_WORDS)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
}
- points.resize (count);
+ if (unlikely (!points.resize (count))) return false;
unsigned int n = 0;
uint16_t i = 0;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint16_t j;
uint8_t control = *p++;
uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
@@ -288,8 +301,7 @@ struct GlyphVariationData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
+ if (unlikely (p + HBUINT16::static_size > end)) return false;
n += *(const HBUINT16 *)p;
points[i] = n;
p += HBUINT16::static_size;
@@ -299,7 +311,7 @@ struct GlyphVariationData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
n += *p++;
points[i] = n;
}
@@ -311,7 +323,7 @@ struct GlyphVariationData
static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<int> &deltas /* IN/OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_delta_flag_t
{
@@ -324,7 +336,7 @@ struct GlyphVariationData
unsigned int count = deltas.length;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint8_t control = *p++;
unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
unsigned int j;
@@ -334,16 +346,14 @@ struct GlyphVariationData
else if (control & DELTAS_ARE_WORDS)
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
+ if (unlikely (p + HBUINT16::static_size > end)) return false;
deltas[i] = *(const HBINT16 *) p;
p += HBUINT16::static_size;
}
else
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range (p)))
- return false;
+ if (unlikely (p + 1 > end)) return false;
deltas[i] = *(const HBINT8 *) p++;
}
if (j < run_count)
@@ -505,19 +515,17 @@ struct gvar
~accelerator_t () { table.destroy (); }
private:
- struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
- struct y_getter { static float get (const contour_point_t &p) { return p.y; } };
- template <typename T>
static float infer_delta (const hb_array_t<contour_point_t> points,
const hb_array_t<contour_point_t> deltas,
- unsigned int target, unsigned int prev, unsigned int next)
+ unsigned int target, unsigned int prev, unsigned int next,
+ float contour_point_t::*m)
{
- float target_val = T::get (points[target]);
- float prev_val = T::get (points[prev]);
- float next_val = T::get (points[next]);
- float prev_delta = T::get (deltas[prev]);
- float next_delta = T::get (deltas[next]);
+ float target_val = points[target].*m;
+ float prev_val = points[prev].*m;
+ float next_val = points[next].*m;
+ float prev_delta = deltas[prev].*m;
+ float next_delta = deltas[next].*m;
if (prev_val == next_val)
return (prev_delta == next_delta) ? prev_delta : 0.f;
@@ -528,7 +536,7 @@ struct gvar
/* linear interpolation */
float r = (target_val - prev_val) / (next_val - prev_val);
- return (1.f - r) * prev_delta + r * next_delta;
+ return prev_delta + r * (next_delta - prev_delta);
}
static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end)
@@ -538,8 +546,7 @@ struct gvar
bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
const hb_array_t<contour_point_t> points) const
{
- /* num_coords should exactly match gvar's axisCount due to how GlyphVariationData tuples are aligned */
- if (!font->num_coords || font->num_coords != table->axisCount) return true;
+ if (!font->num_coords) return true;
if (unlikely (glyph >= table->glyphCount)) return true;
@@ -553,21 +560,25 @@ struct gvar
/* Save original points for inferred delta calculation */
contour_point_vector_t orig_points;
- orig_points.resize (points.length);
+ if (unlikely (!orig_points.resize (points.length))) return false;
for (unsigned int i = 0; i < orig_points.length; i++)
- orig_points[i] = points[i];
+ orig_points.arrayZ[i] = points.arrayZ[i];
contour_point_vector_t deltas; /* flag is used to indicate referenced point */
- deltas.resize (points.length);
+ if (unlikely (!deltas.resize (points.length))) return false;
hb_vector_t<unsigned> end_points;
for (unsigned i = 0; i < points.length; ++i)
if (points[i].is_end_point)
end_points.push (i);
- int *coords = font->coords;
- unsigned num_coords = font->num_coords;
+ auto coords = hb_array (font->coords, font->num_coords);
+ unsigned num_coords = table->axisCount;
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
+
+ hb_vector_t<unsigned int> private_indices;
+ hb_vector_t<int> x_deltas;
+ hb_vector_t<int> y_deltas;
do
{
float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples);
@@ -577,33 +588,30 @@ struct gvar
if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
return false;
- hb_bytes_t bytes ((const char *) p, length);
- hb_vector_t<unsigned int> private_indices;
+ const HBUINT8 *end = p + length;
+
bool has_private_points = iterator.current_tuple->has_private_points ();
if (has_private_points &&
- !GlyphVariationData::unpack_points (p, private_indices, bytes))
+ !GlyphVariationData::unpack_points (p, private_indices, end))
return false;
const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
- hb_vector_t<int> x_deltas;
- x_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, x_deltas, bytes))
- return false;
- hb_vector_t<int> y_deltas;
- y_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, y_deltas, bytes))
- return false;
+ if (unlikely (!x_deltas.resize (num_deltas))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
+ if (unlikely (!y_deltas.resize (num_deltas))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
for (unsigned int i = 0; i < deltas.length; i++)
deltas[i].init ();
for (unsigned int i = 0; i < num_deltas; i++)
{
unsigned int pt_index = apply_to_all ? i : indices[i];
- deltas[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- deltas[pt_index].x += x_deltas[i] * scalar;
- deltas[pt_index].y += y_deltas[i] * scalar;
+ if (unlikely (pt_index >= deltas.length)) continue;
+ deltas.arrayZ[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ deltas.arrayZ[pt_index].x += x_deltas.arrayZ[i] * scalar;
+ deltas.arrayZ[pt_index].y += y_deltas.arrayZ[i] * scalar;
}
/* infer deltas for unreferenced points */
@@ -647,20 +655,20 @@ struct gvar
{
i = next_index (i, start_point, end_point);
if (i == next) break;
- deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
- deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
+ deltas[i].x = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::x);
+ deltas[i].y = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::y);
if (--unref_count == 0) goto no_more_gaps;
}
}
-no_more_gaps:
+ no_more_gaps:
start_point = end_point + 1;
}
/* apply specified / inferred deltas to points */
for (unsigned int i = 0; i < points.length; i++)
{
- points[i].x += deltas[i].x;
- points[i].y += deltas[i].y;
+ points.arrayZ[i].x += deltas.arrayZ[i].x;
+ points.arrayZ[i].y += deltas.arrayZ[i].y;
}
} while (iterator.move_to_next ());
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
index e9d90352f0..56efcdbee9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
@@ -319,10 +319,15 @@ struct HVARVVAR
hvar_plan.index_map_plans.as_array ()));
}
- float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
+ float get_advance_var (hb_codepoint_t glyph,
+ hb_font_t *font,
+ VariationStore::cache_t *store_cache = nullptr) const
{
uint32_t varidx = (this+advMap).map (glyph);
- return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
+ return (this+varStore).get_delta (varidx,
+ font->coords,
+ font->num_coords,
+ store_cache);
}
float get_side_bearing_var (hb_codepoint_t glyph,
@@ -335,7 +340,7 @@ struct HVARVVAR
bool has_side_bearing_deltas () const { return lsbMap && rsbMap; }
- protected:
+ public:
FixedVersion<>version; /* Version of the metrics variation table
* initially set to 0x00010000u */
Offset32To<VariationStore>
diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh
index ce9ff90bb4..683a441ec3 100644
--- a/thirdparty/harfbuzz/src/hb-repacker.hh
+++ b/thirdparty/harfbuzz/src/hb-repacker.hh
@@ -32,1033 +32,18 @@
#include "hb-priority-queue.hh"
#include "hb-serialize.hh"
#include "hb-vector.hh"
+#include "graph/graph.hh"
+#include "graph/serialize.hh"
+
+using graph::graph_t;
/*
* For a detailed writeup on the overflow resolution algorithm see:
* docs/repacker.md
*/
-struct graph_t
-{
- struct vertex_t
- {
- hb_serialize_context_t::object_t obj;
- int64_t distance = 0 ;
- int64_t space = 0 ;
- hb_vector_t<unsigned> parents;
- unsigned start = 0;
- unsigned end = 0;
- unsigned priority = 0;
-
- friend void swap (vertex_t& a, vertex_t& b)
- {
- hb_swap (a.obj, b.obj);
- hb_swap (a.distance, b.distance);
- hb_swap (a.space, b.space);
- hb_swap (a.parents, b.parents);
- hb_swap (a.start, b.start);
- hb_swap (a.end, b.end);
- hb_swap (a.priority, b.priority);
- }
-
- bool is_shared () const
- {
- return parents.length > 1;
- }
-
- unsigned incoming_edges () const
- {
- return parents.length;
- }
-
- void remove_parent (unsigned parent_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] != parent_index) continue;
- parents.remove (i);
- break;
- }
- }
-
- void remap_parents (const hb_vector_t<unsigned>& id_map)
- {
- for (unsigned i = 0; i < parents.length; i++)
- parents[i] = id_map[parents[i]];
- }
-
- void remap_parent (unsigned old_index, unsigned new_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] == old_index)
- parents[i] = new_index;
- }
- }
-
- bool is_leaf () const
- {
- return !obj.real_links.length && !obj.virtual_links.length;
- }
-
- bool raise_priority ()
- {
- if (has_max_priority ()) return false;
- priority++;
- return true;
- }
-
- bool has_max_priority () const {
- return priority >= 3;
- }
-
- int64_t modified_distance (unsigned order) const
- {
- // TODO(garretrieger): once priority is high enough, should try
- // setting distance = 0 which will force to sort immediately after
- // it's parent where possible.
-
- int64_t modified_distance =
- hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
- if (has_max_priority ()) {
- modified_distance = 0;
- }
- return (modified_distance << 18) | (0x003FFFF & order);
- }
-
- int64_t distance_modifier () const
- {
- if (!priority) return 0;
- int64_t table_size = obj.tail - obj.head;
-
- if (priority == 1)
- return -table_size / 2;
-
- return -table_size;
- }
- };
-
- struct overflow_record_t
- {
- unsigned parent;
- unsigned child;
- };
-
- /*
- * A topological sorting of an object graph. Ordered
- * in reverse serialization order (first object in the
- * serialization is at the end of the list). This matches
- * the 'packed' object stack used internally in the
- * serializer
- */
- template<typename T>
- graph_t (const T& objects)
- : parents_invalid (true),
- distance_invalid (true),
- positions_invalid (true),
- successful (true)
- {
- num_roots_for_space_.push (1);
- bool removed_nil = false;
- vertices_.alloc (objects.length);
- vertices_scratch_.alloc (objects.length);
- for (unsigned i = 0; i < objects.length; i++)
- {
- // TODO(grieger): check all links point to valid objects.
-
- // If this graph came from a serialization buffer object 0 is the
- // nil object. We don't need it for our purposes here so drop it.
- if (i == 0 && !objects[i])
- {
- removed_nil = true;
- continue;
- }
-
- vertex_t* v = vertices_.push ();
- if (check_success (!vertices_.in_error ()))
- v->obj = *objects[i];
- if (!removed_nil) continue;
- // Fix indices to account for removed nil object.
- for (auto& l : v->obj.all_links_writer ()) {
- l.objidx--;
- }
- }
- }
-
- ~graph_t ()
- {
- vertices_.fini ();
- }
-
- bool in_error () const
- {
- return !successful ||
- vertices_.in_error () ||
- num_roots_for_space_.in_error ();
- }
-
- const vertex_t& root () const
- {
- return vertices_[root_idx ()];
- }
-
- unsigned root_idx () const
- {
- // Object graphs are in reverse order, the first object is at the end
- // of the vector. Since the graph is topologically sorted it's safe to
- // assume the first object has no incoming edges.
- return vertices_.length - 1;
- }
-
- const hb_serialize_context_t::object_t& object(unsigned i) const
- {
- return vertices_[i].obj;
- }
-
- /*
- * serialize graph into the provided serialization buffer.
- */
- hb_blob_t* serialize () const
- {
- hb_vector_t<char> buffer;
- size_t size = serialized_length ();
- if (!buffer.alloc (size)) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
- return nullptr;
- }
- hb_serialize_context_t c((void *) buffer, size);
-
- c.start_serialize<void> ();
- for (unsigned i = 0; i < vertices_.length; i++) {
- c.push ();
-
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- char* start = c.allocate_size <char> (size);
- if (!start) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
- return nullptr;
- }
-
- memcpy (start, vertices_[i].obj.head, size);
-
- // Only real links needs to be serialized.
- for (const auto& link : vertices_[i].obj.real_links)
- serialize_link (link, start, &c);
-
- // All duplications are already encoded in the graph, so don't
- // enable sharing during packing.
- c.pop_pack (false);
- }
- c.end_serialize ();
-
- if (c.in_error ()) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
- c.errors);
- return nullptr;
- }
-
- return c.copy_blob ();
- }
-
- /*
- * Generates a new topological sorting of graph ordered by the shortest
- * distance to each node.
- */
- void sort_shortest_distance ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- update_distances ();
-
- hb_priority_queue_t queue;
- hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.insert (root ().modified_distance (0), root_idx ());
- int new_id = root_idx ();
- unsigned order = 1;
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_id = queue.pop_minimum().second;
-
- hb_swap (sorted_graph[new_id], vertices_[next_id]);
- const vertex_t& next = sorted_graph[new_id];
-
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- // Add the order that the links were encountered to the priority.
- // This ensures that ties between priorities objects are broken in a consistent
- // way. More specifically this is set up so that if a set of objects have the same
- // distance they'll be added to the topological order in the order that they are
- // referenced from the parent object.
- queue.insert (vertices_[link.objidx].modified_distance (order++),
- link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- }
-
- /*
- * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
- */
- bool assign_32bit_spaces ()
- {
- unsigned root_index = root_idx ();
- hb_set_t visited;
- hb_set_t roots;
- for (unsigned i = 0; i <= root_index; i++)
- {
- // Only real links can form 32 bit spaces
- for (auto& l : vertices_[i].obj.real_links)
- {
- if (l.width == 4 && !l.is_signed)
- {
- roots.add (l.objidx);
- find_subgraph (l.objidx, visited);
- }
- }
- }
-
- // Mark everything not in the subgraphs of 32 bit roots as visited.
- // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
- visited.invert ();
-
- if (!roots) return false;
-
- while (roots)
- {
- unsigned next = HB_SET_VALUE_INVALID;
- if (unlikely (!check_success (!roots.in_error ()))) break;
- if (!roots.next (&next)) break;
-
- hb_set_t connected_roots;
- find_connected_nodes (next, roots, visited, connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- isolate_subgraph (connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- unsigned next_space = this->next_space ();
- num_roots_for_space_.push (0);
- for (unsigned root : connected_roots)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
- vertices_[root].space = next_space;
- num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
- distance_invalid = true;
- positions_invalid = true;
- }
-
- // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
- // into the 32 bit space as needed, instead of using isolation.
- }
-
-
-
- return true;
- }
-
- /*
- * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
- * that originate from outside of the subgraph will be removed by duplicating the linked to
- * object.
- *
- * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
- */
- bool isolate_subgraph (hb_set_t& roots)
- {
- update_parents ();
- hb_hashmap_t<unsigned, unsigned> subgraph;
-
- // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
- // set the subgraph incoming edge count to match all of root_idx's incoming edges
- hb_set_t parents;
- for (unsigned root_idx : roots)
- {
- subgraph.set (root_idx, wide_parents (root_idx, parents));
- find_subgraph (root_idx, subgraph);
- }
-
- unsigned original_root_idx = root_idx ();
- hb_hashmap_t<unsigned, unsigned> index_map;
- bool made_changes = false;
- for (auto entry : subgraph.iter ())
- {
- const auto& node = vertices_[entry.first];
- unsigned subgraph_incoming_edges = entry.second;
-
- if (subgraph_incoming_edges < node.incoming_edges ())
- {
- // Only de-dup objects with incoming links from outside the subgraph.
- made_changes = true;
- duplicate_subgraph (entry.first, index_map);
- }
- }
-
- if (!made_changes)
- return false;
-
- if (original_root_idx != root_idx ()
- && parents.has (original_root_idx))
- {
- // If the root idx has changed since parents was determined, update root idx in parents
- parents.add (root_idx ());
- parents.del (original_root_idx);
- }
-
- auto new_subgraph =
- + subgraph.keys ()
- | hb_map([&] (unsigned node_idx) {
- if (index_map.has (node_idx)) return index_map[node_idx];
- return node_idx;
- })
- ;
-
- remap_obj_indices (index_map, new_subgraph);
- remap_obj_indices (index_map, parents.iter (), true);
-
- // Update roots set with new indices as needed.
- unsigned next = HB_SET_VALUE_INVALID;
- while (roots.next (&next))
- {
- if (index_map.has (next))
- {
- roots.del (next);
- roots.add (index_map[next]);
- }
- }
-
- return true;
- }
-
- void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
- {
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- {
- if (subgraph.has (link.objidx))
- {
- subgraph.set (link.objidx, subgraph[link.objidx] + 1);
- continue;
- }
- subgraph.set (link.objidx, 1);
- find_subgraph (link.objidx, subgraph);
- }
- }
-
- void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
- {
- if (subgraph.has (node_idx)) return;
- subgraph.add (node_idx);
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- find_subgraph (link.objidx, subgraph);
- }
-
- /*
- * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
- * links. index_map is updated with mappings from old id to new id. If a duplication has already
- * been performed for a given index, then it will be skipped.
- */
- void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map)
- {
- if (index_map.has (node_idx))
- return;
-
- index_map.set (node_idx, duplicate (node_idx));
- for (const auto& l : object (node_idx).all_links ()) {
- duplicate_subgraph (l.objidx, index_map);
- }
- }
-
- /*
- * Creates a copy of node_idx and returns it's new index.
- */
- unsigned duplicate (unsigned node_idx)
- {
- positions_invalid = true;
- distance_invalid = true;
-
- auto* clone = vertices_.push ();
- auto& child = vertices_[node_idx];
- if (vertices_.in_error ()) {
- return -1;
- }
-
- clone->obj.head = child.obj.head;
- clone->obj.tail = child.obj.tail;
- clone->distance = child.distance;
- clone->space = child.space;
- clone->parents.reset ();
-
- unsigned clone_idx = vertices_.length - 2;
- for (const auto& l : child.obj.real_links)
- {
- clone->obj.real_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
- }
- for (const auto& l : child.obj.virtual_links)
- {
- clone->obj.virtual_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
- }
-
- check_success (!clone->obj.real_links.in_error ());
- check_success (!clone->obj.virtual_links.in_error ());
-
- // The last object is the root of the graph, so swap back the root to the end.
- // The root's obj idx does change, however since it's root nothing else refers to it.
- // all other obj idx's will be unaffected.
- hb_swap (vertices_[vertices_.length - 2], *clone);
-
- // Since the root moved, update the parents arrays of all children on the root.
- for (const auto& l : root ().obj.all_links ())
- vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
-
- return clone_idx;
- }
-
- /*
- * Creates a copy of child and re-assigns the link from
- * parent to the clone. The copy is a shallow copy, objects
- * linked from child are not duplicated.
- */
- bool duplicate (unsigned parent_idx, unsigned child_idx)
- {
- update_parents ();
-
- unsigned links_to_child = 0;
- for (const auto& l : vertices_[parent_idx].obj.all_links ())
- {
- if (l.objidx == child_idx) links_to_child++;
- }
-
- if (vertices_[child_idx].incoming_edges () <= links_to_child)
- {
- // Can't duplicate this node, doing so would orphan the original one as all remaining links
- // to child are from parent.
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
- parent_idx, child_idx);
- return false;
- }
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
- parent_idx, child_idx);
-
- unsigned clone_idx = duplicate (child_idx);
- if (clone_idx == (unsigned) -1) return false;
- // duplicate shifts the root node idx, so if parent_idx was root update it.
- if (parent_idx == clone_idx) parent_idx++;
-
- auto& parent = vertices_[parent_idx];
- for (auto& l : parent.obj.all_links_writer ())
- {
- if (l.objidx != child_idx)
- continue;
-
- reassign_link (l, parent_idx, clone_idx);
- }
-
- return true;
- }
-
- /*
- * Raises the sorting priority of all children.
- */
- bool raise_childrens_priority (unsigned parent_idx)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
- parent_idx);
- // This operation doesn't change ordering until a sort is run, so no need
- // to invalidate positions. It does not change graph structure so no need
- // to update distances or edge counts.
- auto& parent = vertices_[parent_idx].obj;
- bool made_change = false;
- for (auto& l : parent.all_links_writer ())
- made_change |= vertices_[l.objidx].raise_priority ();
- return made_change;
- }
-
- /*
- * Will any offsets overflow on graph when it's serialized?
- */
- bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr)
- {
- if (overflows) overflows->resize (0);
- update_positions ();
-
- for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
- {
- // Don't need to check virtual links for overflow
- for (const auto& link : vertices_[parent_idx].obj.real_links)
- {
- int64_t offset = compute_offset (parent_idx, link);
- if (is_valid_offset (offset, link))
- continue;
-
- if (!overflows) return true;
-
- overflow_record_t r;
- r.parent = parent_idx;
- r.child = link.objidx;
- overflows->push (r);
- }
- }
-
- if (!overflows) return false;
- return overflows->length;
- }
-
- void print_orphaned_nodes ()
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
- parents_invalid = true;
- update_parents();
-
- for (unsigned i = 0; i < root_idx (); i++)
- {
- const auto& v = vertices_[i];
- if (!v.parents)
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
- }
- }
-
- void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- update_parents ();
- int limit = 10;
- for (const auto& o : overflows)
- {
- if (!limit--) break;
- const auto& parent = vertices_[o.parent];
- const auto& child = vertices_[o.child];
- DEBUG_MSG (SUBSET_REPACK, nullptr,
- " overflow from "
- "%4d (%4d in, %4d out, space %2d) => "
- "%4d (%4d in, %4d out, space %2d)",
- o.parent,
- parent.incoming_edges (),
- parent.obj.real_links.length + parent.obj.virtual_links.length,
- space_for (o.parent),
- o.child,
- child.incoming_edges (),
- child.obj.real_links.length + child.obj.virtual_links.length,
- space_for (o.child));
- }
- if (overflows.length > 10) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
- }
- }
-
- unsigned num_roots_for_space (unsigned space) const
- {
- return num_roots_for_space_[space];
- }
-
- unsigned next_space () const
- {
- return num_roots_for_space_.length;
- }
-
- void move_to_new_space (const hb_set_t& indices)
- {
- num_roots_for_space_.push (0);
- unsigned new_space = num_roots_for_space_.length - 1;
-
- for (unsigned index : indices) {
- auto& node = vertices_[index];
- num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
- num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
- node.space = new_space;
- distance_invalid = true;
- positions_invalid = true;
- }
- }
-
- unsigned space_for (unsigned index, unsigned* root = nullptr) const
- {
- const auto& node = vertices_[index];
- if (node.space)
- {
- if (root != nullptr)
- *root = index;
- return node.space;
- }
-
- if (!node.parents)
- {
- if (root)
- *root = index;
- return 0;
- }
-
- return space_for (node.parents[0], root);
- }
-
- void err_other_error () { this->successful = false; }
-
- private:
-
- size_t serialized_length () const {
- size_t total_size = 0;
- for (unsigned i = 0; i < vertices_.length; i++) {
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- total_size += size;
- }
- return total_size;
- }
-
- /*
- * Returns the numbers of incoming edges that are 32bits wide.
- */
- unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
- {
- unsigned count = 0;
- hb_set_t visited;
- for (unsigned p : vertices_[node_idx].parents)
- {
- if (visited.has (p)) continue;
- visited.add (p);
-
- // Only real links can be wide
- for (const auto& l : vertices_[p].obj.real_links)
- {
- if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
- {
- count++;
- parents.add (p);
- }
- }
- }
- return count;
- }
-
- bool check_success (bool success)
- { return this->successful && (success || (err_other_error (), false)); }
-
- /*
- * Creates a map from objid to # of incoming edges.
- */
- void update_parents ()
- {
- if (!parents_invalid) return;
-
- for (unsigned i = 0; i < vertices_.length; i++)
- vertices_[i].parents.reset ();
-
- for (unsigned p = 0; p < vertices_.length; p++)
- {
- for (auto& l : vertices_[p].obj.all_links ())
- {
- vertices_[l.objidx].parents.push (p);
- }
- }
-
- parents_invalid = false;
- }
-
- /*
- * compute the serialized start and end positions for each vertex.
- */
- void update_positions ()
- {
- if (!positions_invalid) return;
-
- unsigned current_pos = 0;
- for (int i = root_idx (); i >= 0; i--)
- {
- auto& v = vertices_[i];
- v.start = current_pos;
- current_pos += v.obj.tail - v.obj.head;
- v.end = current_pos;
- }
-
- positions_invalid = false;
- }
-
- /*
- * Finds the distance to each object in the graph
- * from the initial node.
- */
- void update_distances ()
- {
- if (!distance_invalid) return;
-
- // Uses Dijkstra's algorithm to find all of the shortest distances.
- // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
- //
- // Implementation Note:
- // Since our priority queue doesn't support fast priority decreases
- // we instead just add new entries into the queue when a priority changes.
- // Redundant ones are filtered out later on by the visited set.
- // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
- // for practical performance this is faster then using a more advanced queue
- // (such as a fibonacci queue) with a fast decrease priority.
- for (unsigned i = 0; i < vertices_.length; i++)
- {
- if (i == vertices_.length - 1)
- vertices_[i].distance = 0;
- else
- vertices_[i].distance = hb_int_max (int64_t);
- }
-
- hb_priority_queue_t queue;
- queue.insert (0, vertices_.length - 1);
-
- hb_vector_t<bool> visited;
- visited.resize (vertices_.length);
-
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_idx = queue.pop_minimum ().second;
- if (visited[next_idx]) continue;
- const auto& next = vertices_[next_idx];
- int64_t next_distance = vertices_[next_idx].distance;
- visited[next_idx] = true;
-
- for (const auto& link : next.obj.all_links ())
- {
- if (visited[link.objidx]) continue;
-
- const auto& child = vertices_[link.objidx].obj;
- unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
- int64_t child_weight = (child.tail - child.head) +
- ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
- int64_t child_distance = next_distance + child_weight;
-
- if (child_distance < vertices_[link.objidx].distance)
- {
- vertices_[link.objidx].distance = child_distance;
- queue.insert (child_distance, link.objidx);
- }
- }
- }
-
- check_success (!queue.in_error ());
- if (!check_success (queue.is_empty ()))
- {
- print_orphaned_nodes ();
- return;
- }
-
- distance_invalid = false;
- }
-
- int64_t compute_offset (
- unsigned parent_idx,
- const hb_serialize_context_t::object_t::link_t& link) const
- {
- const auto& parent = vertices_[parent_idx];
- const auto& child = vertices_[link.objidx];
- int64_t offset = 0;
- switch ((hb_serialize_context_t::whence_t) link.whence) {
- case hb_serialize_context_t::whence_t::Head:
- offset = child.start - parent.start; break;
- case hb_serialize_context_t::whence_t::Tail:
- offset = child.start - parent.end; break;
- case hb_serialize_context_t::whence_t::Absolute:
- offset = child.start; break;
- }
-
- assert (offset >= link.bias);
- offset -= link.bias;
- return offset;
- }
-
- bool is_valid_offset (int64_t offset,
- const hb_serialize_context_t::object_t::link_t& link) const
- {
- if (unlikely (!link.width))
- // Virtual links can't overflow.
- return link.is_signed || offset >= 0;
-
- if (link.is_signed)
- {
- if (link.width == 4)
- return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
- else
- return offset >= -(1 << 15) && offset < (1 << 15);
- }
- else
- {
- if (link.width == 4)
- return offset >= 0 && offset < ((int64_t) 1 << 32);
- else if (link.width == 3)
- return offset >= 0 && offset < ((int32_t) 1 << 24);
- else
- return offset >= 0 && offset < (1 << 16);
- }
- }
-
- /*
- * Updates a link in the graph to point to a different object. Corrects the
- * parents vector on the previous and new child nodes.
- */
- void reassign_link (hb_serialize_context_t::object_t::link_t& link,
- unsigned parent_idx,
- unsigned new_idx)
- {
- unsigned old_idx = link.objidx;
- link.objidx = new_idx;
- vertices_[old_idx].remove_parent (parent_idx);
- vertices_[new_idx].parents.push (parent_idx);
- }
-
- /*
- * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
- */
- template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
- void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
- Iterator subgraph,
- bool only_wide = false)
- {
- if (!id_map) return;
- for (unsigned i : subgraph)
- {
- for (auto& link : vertices_[i].obj.all_links_writer ())
- {
- if (!id_map.has (link.objidx)) continue;
- if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
-
- reassign_link (link, i, id_map[link.objidx]);
- }
- }
- }
-
- /*
- * Updates all objidx's in all links using the provided mapping.
- */
- void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
- hb_vector_t<vertex_t>* sorted_graph) const
- {
- for (unsigned i = 0; i < sorted_graph->length; i++)
- {
- (*sorted_graph)[i].remap_parents (id_map);
- for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
- {
- link.objidx = id_map[link.objidx];
- }
- }
- }
-
- template <typename O> void
- serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
- *offset = 0;
- c->add_link (*offset,
- // serializer has an extra nil object at the start of the
- // object array. So all id's are +1 of what our id's are.
- link.objidx + 1,
- (hb_serialize_context_t::whence_t) link.whence,
- link.bias);
- }
-
- void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- switch (link.width)
- {
- case 0:
- // Virtual links aren't serialized.
- return;
- case 4:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT32> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT32> (link, head, c);
- }
- return;
- case 2:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT16> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT16> (link, head, c);
- }
- return;
- case 3:
- serialize_link_of_type<OT::HBUINT24> (link, head, c);
- return;
- default:
- // Unexpected link width.
- assert (0);
- }
- }
-
- /*
- * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
- * For this search the graph is treated as being undirected.
- *
- * Connected targets will be added to connected and removed from targets. All visited nodes
- * will be added to visited.
- */
- void find_connected_nodes (unsigned start_idx,
- hb_set_t& targets,
- hb_set_t& visited,
- hb_set_t& connected)
- {
- if (unlikely (!check_success (!visited.in_error ()))) return;
- if (visited.has (start_idx)) return;
- visited.add (start_idx);
-
- if (targets.has (start_idx))
- {
- targets.del (start_idx);
- connected.add (start_idx);
- }
-
- const auto& v = vertices_[start_idx];
-
- // Graph is treated as undirected so search children and parents of start_idx
- for (const auto& l : v.obj.all_links ())
- find_connected_nodes (l.objidx, targets, visited, connected);
-
- for (unsigned p : v.parents)
- find_connected_nodes (p, targets, visited, connected);
- }
-
- public:
- // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
- hb_vector_t<vertex_t> vertices_;
- hb_vector_t<vertex_t> vertices_scratch_;
- private:
- bool parents_invalid;
- bool distance_invalid;
- bool positions_invalid;
- bool successful;
- hb_vector_t<unsigned> num_roots_for_space_;
-};
static inline
-bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& overflows,
graph_t& sorted_graph)
{
unsigned space = 0;
@@ -1066,7 +51,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& ov
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
unsigned root;
unsigned overflow_space = sorted_graph.space_for (r.parent, &root);
@@ -1108,7 +93,7 @@ bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& ov
}
static inline
-bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
hb_set_t& priority_bumped_parents,
graph_t& sorted_graph)
{
@@ -1117,7 +102,7 @@ bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflow
// Try resolving the furthest overflows first.
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
const auto& child = sorted_graph.vertices_[r.child];
if (child.is_shared ())
{
@@ -1173,19 +158,18 @@ inline hb_blob_t*
hb_resolve_overflows (const T& packed,
hb_tag_t table_tag,
unsigned max_rounds = 20) {
- // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
- // so try it first to save time.
graph_t sorted_graph (packed);
- if (!sorted_graph.will_overflow ())
+ sorted_graph.sort_shortest_distance ();
+
+ bool will_overflow = graph::will_overflow (sorted_graph);
+ if (!will_overflow)
{
- return sorted_graph.serialize ();
+ return graph::serialize (sorted_graph);
}
- sorted_graph.sort_shortest_distance ();
-
if ((table_tag == HB_OT_TAG_GPOS
|| table_tag == HB_OT_TAG_GSUB)
- && sorted_graph.will_overflow ())
+ && will_overflow)
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
if (sorted_graph.assign_32bit_spaces ())
@@ -1193,13 +177,13 @@ hb_resolve_overflows (const T& packed,
}
unsigned round = 0;
- hb_vector_t<graph_t::overflow_record_t> overflows;
+ hb_vector_t<graph::overflow_record_t> overflows;
// TODO(garretrieger): select a good limit for max rounds.
while (!sorted_graph.in_error ()
- && sorted_graph.will_overflow (&overflows)
+ && graph::will_overflow (sorted_graph, &overflows)
&& round++ < max_rounds) {
DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
- sorted_graph.print_overflows (overflows);
+ print_overflows (sorted_graph, overflows);
hb_set_t priority_bumped_parents;
@@ -1221,13 +205,13 @@ hb_resolve_overflows (const T& packed,
return nullptr;
}
- if (sorted_graph.will_overflow ())
+ if (graph::will_overflow (sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
return nullptr;
}
- return sorted_graph.serialize ();
+ return graph::serialize (sorted_graph);
}
#endif /* HB_REPACKER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh
index 5663b290c3..cecdcdeb74 100644
--- a/thirdparty/harfbuzz/src/hb-serialize.hh
+++ b/thirdparty/harfbuzz/src/hb-serialize.hh
@@ -695,7 +695,7 @@ struct hb_serialize_context_t
check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
}
- public: /* TODO Make private. */
+ public:
char *start, *head, *tail, *end;
unsigned int debug_depth;
hb_serialize_error_t errors;
@@ -719,9 +719,7 @@ struct hb_serialize_context_t
hb_vector_t<object_t *> packed;
/* Map view of packed objects. */
- hb_hashmap_t<const object_t *, objidx_t,
- const object_t *, objidx_t,
- nullptr, 0> packed_map;
+ hb_hashmap_t<const object_t *, objidx_t> packed_map;
};
#endif /* HB_SERIALIZE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh
index 7d4979b73b..fab36216e4 100644
--- a/thirdparty/harfbuzz/src/hb-set-digest.hh
+++ b/thirdparty/harfbuzz/src/hb-set-digest.hh
@@ -30,7 +30,7 @@
#include "hb.hh"
/*
- * The set digests here implement various "filters" that support
+ * The set-digests here implement various "filters" that support
* "approximate member query". Conceptually these are like Bloom
* Filter and Quotient Filter, however, much smaller, faster, and
* designed to fit the requirements of our uses for glyph coverage
@@ -40,13 +40,25 @@
* set of glyphs, but fully flooded and ineffective if coverage is
* all over the place.
*
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
+ * The way these are used is that the filter is first populated by
+ * a lookup's or subtable's Coverage table(s), and then when we
+ * want to apply the lookup or subtable to a glyph, before trying
+ * to apply, we ask the filter if the glyph may be covered. If it's
+ * not, we return early.
+ *
+ * We use these filters both at the lookup-level, and then again,
+ * at the subtable-level. Both have performance win.
+ *
+ * The main filter we use is a combination of three bits-pattern
+ * filters. A bits-pattern filter checks a number of bits (5 or 6)
+ * of the input number (glyph-id in this case) and checks whether
+ * its pattern is amongst the patterns of any of the accepted values.
+ * The accepted patterns are represented as a "long" integer. The
+ * check is done using four bitwise operations only.
*/
template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
+struct hb_set_digest_bits_pattern_t
{
static constexpr unsigned mask_bytes = sizeof (mask_t);
static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
@@ -102,7 +114,7 @@ struct hb_set_digest_lowest_bits_t
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
bool may_have (hb_codepoint_t g) const
- { return !!(mask & mask_for (g)); }
+ { return mask & mask_for (g); }
private:
@@ -171,11 +183,11 @@ struct hb_set_digest_combiner_t
using hb_set_digest_t =
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 4>,
+ hb_set_digest_bits_pattern_t<unsigned long, 4>,
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 0>,
- hb_set_digest_lowest_bits_t<unsigned long, 9>
+ hb_set_digest_bits_pattern_t<unsigned long, 0>,
+ hb_set_digest_bits_pattern_t<unsigned long, 9>
>
>
;
diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc
index 0e2c1f77ef..2d458294f8 100644
--- a/thirdparty/harfbuzz/src/hb-set.cc
+++ b/thirdparty/harfbuzz/src/hb-set.cc
@@ -40,7 +40,7 @@
/**
- * hb_set_create: (Xconstructor)
+ * hb_set_create:
*
* Creates a new, initially empty set.
*
@@ -186,6 +186,7 @@ hb_set_t *
hb_set_copy (const hb_set_t *set)
{
hb_set_t *copy = hb_set_create ();
+ if (unlikely (!copy)) return nullptr;
copy->set (*set);
return copy;
}
@@ -359,6 +360,23 @@ hb_set_is_equal (const hb_set_t *set,
}
/**
+ * hb_set_hash:
+ * @set: A set
+ *
+ * Creates a hash representing @set.
+ *
+ * Return value:
+ * A hash of @set.
+ *
+ * Since: 4.4.0
+ **/
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set)
+{
+ return set->hash ();
+}
+
+/**
* hb_set_is_subset:
* @set: A set
* @larger_set: Another set
diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h
index 10ce7c10d4..56902c267e 100644
--- a/thirdparty/harfbuzz/src/hb-set.h
+++ b/thirdparty/harfbuzz/src/hb-set.h
@@ -128,6 +128,9 @@ HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set);
+
HB_EXTERN hb_bool_t
hb_set_is_subset (const hb_set_t *set,
const hb_set_t *larger_set);
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index 6025626363..7eb5e19a2a 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -166,7 +166,6 @@ struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
~hb_set_t () = default;
hb_set_t () : sparseset () {};
- hb_set_t (std::nullptr_t) : hb_set_t () {};
hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
hb_set_t& operator = (const hb_set_t&) = default;
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc
index 66332165c3..0af07825fc 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc
@@ -170,7 +170,7 @@ hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
/**
- * hb_shape_plan_create: (Xconstructor)
+ * hb_shape_plan_create:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -198,7 +198,7 @@ hb_shape_plan_create (hb_face_t *face,
}
/**
- * hb_shape_plan_create2: (Xconstructor)
+ * hb_shape_plan_create2:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -231,7 +231,8 @@ hb_shape_plan_create2 (hb_face_t *face,
num_coords,
shaper_list);
- assert (props->direction != HB_DIRECTION_INVALID);
+ if (unlikely (props->direction == HB_DIRECTION_INVALID))
+ return hb_shape_plan_get_empty ();
hb_shape_plan_t *shape_plan;
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index 3407e1af42..14ec92828f 100644
--- a/thirdparty/harfbuzz/src/hb-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-shape.cc
@@ -50,7 +50,7 @@
static inline void free_static_shaper_list ();
-static const char *nil_shaper_list[] = {nullptr};
+static const char * const nil_shaper_list[] = {nullptr};
static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
hb_shaper_list_lazy_loader_t>
@@ -73,7 +73,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
}
static void destroy (const char **l)
{ hb_free (l); }
- static const char ** get_null ()
+ static const char * const * get_null ()
{ return nil_shaper_list; }
} static_shaper_list;
@@ -126,6 +126,11 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
+ if (unlikely (!buffer->len))
+ return true;
+
+ buffer->enter ();
+
hb_buffer_t *text_buffer = nullptr;
if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
{
@@ -137,12 +142,19 @@ hb_shape_full (hb_font_t *font,
features, num_features,
font->coords, font->num_coords,
shaper_list);
+
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
+
+ if (buffer->max_ops <= 0)
+ buffer->shaping_failed = true;
+
hb_shape_plan_destroy (shape_plan);
if (text_buffer)
{
- if (res && !buffer->verify (text_buffer,
+ if (res && buffer->successful && !buffer->shaping_failed
+ && text_buffer->successful
+ && !buffer->verify (text_buffer,
font,
features,
num_features,
@@ -151,6 +163,8 @@ hb_shape_full (hb_font_t *font,
hb_buffer_destroy (text_buffer);
}
+ buffer->leave ();
+
return res;
}
diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc
index a11ed83afd..da4253ed64 100644
--- a/thirdparty/harfbuzz/src/hb-shaper.cc
+++ b/thirdparty/harfbuzz/src/hb-shaper.cc
@@ -29,18 +29,18 @@
#include "hb-machinery.hh"
-static const hb_shaper_entry_t all_shapers[] = {
+static const hb_shaper_entry_t _hb_all_shapers[] = {
#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
};
#ifndef HB_NO_SHAPER
-static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled.");
+static_assert (0 != ARRAY_LENGTH_CONST (_hb_all_shapers), "No shaper enabled.");
#endif
static inline void free_static_shapers ();
-static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t,
hb_shapers_lazy_loader_t>
{
static hb_shaper_entry_t *create ()
@@ -49,11 +49,11 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!env || !*env)
return nullptr;
- hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (all_shapers));
+ hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (_hb_all_shapers));
if (unlikely (!shapers))
return nullptr;
- memcpy (shapers, all_shapers, sizeof (all_shapers));
+ memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
@@ -64,7 +64,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!end)
end = p + strlen (p);
- for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++)
+ for (unsigned int j = i; j < ARRAY_LENGTH (_hb_all_shapers); j++)
if (end - p == (int) strlen (shapers[j].name) &&
0 == strncmp (shapers[j].name, p, end - p))
{
@@ -85,8 +85,8 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
return shapers;
}
- static void destroy (const hb_shaper_entry_t *p) { hb_free ((void *) p); }
- static const hb_shaper_entry_t *get_null () { return all_shapers; }
+ static void destroy (hb_shaper_entry_t *p) { hb_free (p); }
+ static const hb_shaper_entry_t *get_null () { return _hb_all_shapers; }
} static_shapers;
static inline
diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc
index 7cc51be611..5c5ecce880 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -53,6 +53,9 @@ DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+/* hb_map_t */
+
+const hb_codepoint_t minus_1 = -1;
/* hb_face_t */
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
index ae155b4e3c..bb9f27eec1 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
@@ -44,7 +44,8 @@ struct str_encoder_t
void encode_byte (unsigned char b)
{
- if (unlikely (buff.push (b) == &Crap (unsigned char)))
+ buff.push (b);
+ if (unlikely (buff.in_error ()))
set_error ();
}
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc
index 4885280996..028ddf9035 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-input.cc
@@ -140,7 +140,20 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('r', 't', 'l', 'a'),
HB_TAG ('r', 't', 'l', 'm'),
- //Complex shapers
+ //random
+ HB_TAG ('r', 'a', 'n', 'd'),
+
+ //justify
+ HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might
+
+ //private
+ HB_TAG ('H', 'a', 'r', 'f'),
+ HB_TAG ('H', 'A', 'R', 'F'),
+ HB_TAG ('B', 'u', 'z', 'z'),
+ HB_TAG ('B', 'U', 'Z', 'Z'),
+
+ //shapers
+
//arabic
HB_TAG ('i', 'n', 'i', 't'),
HB_TAG ('m', 'e', 'd', 'i'),
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index a62ae8e024..4e3bb1d477 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -41,9 +41,9 @@
#include "hb-ot-math-table.hh"
using OT::Layout::GSUB::GSUB;
+using OT::Layout::GPOS;
-
-typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
+typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
static inline void
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
@@ -204,7 +204,7 @@ static inline void
hb_map_t *layout_variation_idx_map)
{
hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
- hb_blob_ptr_t<OT::GPOS> gpos = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
+ hb_blob_ptr_t<GPOS> gpos = hb_sanitize_context_t ().reference_table<GPOS> (face);
if (!gdef->has_data ())
{
@@ -347,13 +347,42 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
}
+#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
+#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
+#endif
+
+static unsigned
+_glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
+ hb_codepoint_t gid,
+ hb_set_t *gids_to_retain,
+ int operation_count,
+ unsigned depth = 0)
+{
+ if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
+ if (unlikely (--operation_count < 0)) return operation_count;
+ /* Check if is already visited */
+ if (gids_to_retain->has (gid)) return operation_count;
+
+ gids_to_retain->add (gid);
+
+ for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
+ operation_count =
+ _glyf_add_gid_and_children (glyf,
+ item.glyphIndex,
+ gids_to_retain,
+ operation_count,
+ depth);
+
+ return operation_count;
+}
+
static void
_populate_gids_to_retain (hb_subset_plan_t* plan,
bool close_over_gsub,
bool close_over_gpos,
bool close_over_gdef)
{
- OT::glyf::accelerator_t glyf (plan->source);
+ OT::glyf_accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
OT::cff1::accelerator_t cff (plan->source);
#endif
@@ -374,7 +403,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
plan->gsub_langsys);
if (close_over_gpos)
- _closure_glyphs_lookups_features<OT::GPOS> (
+ _closure_glyphs_lookups_features<GPOS> (
plan->source,
plan->_glyphset_gsub,
plan->layout_features,
@@ -398,7 +427,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
* composite glyphs. */
if (glyf.has_data ())
for (hb_codepoint_t gid : cur_glyphset)
- glyf.add_gid_and_children (gid, plan->_glyphset);
+ _glyf_add_gid_and_children (glyf, gid, plan->_glyphset,
+ cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
else
plan->_glyphset->union_ (cur_glyphset);
#ifndef HB_NO_SUBSET_CFF
@@ -630,9 +660,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (plan->gsub_langsys)
{
- for (auto _ : plan->gsub_langsys->iter ())
- hb_set_destroy (_.second);
-
hb_object_destroy (plan->gsub_langsys);
plan->gsub_langsys->fini_shallow ();
hb_free (plan->gsub_langsys);
@@ -640,9 +667,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (plan->gpos_langsys)
{
- for (auto _ : plan->gpos_langsys->iter ())
- hb_set_destroy (_.second);
-
hb_object_destroy (plan->gpos_langsys);
plan->gpos_langsys->fini_shallow ();
hb_free (plan->gpos_langsys);
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index cb567b769e..2aaf19c61d 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -87,8 +87,8 @@ struct hb_subset_plan_t
hb_map_t *gpos_lookups;
//active langsys we'd like to retain
- hb_hashmap_t<unsigned, hb_set_t *> *gsub_langsys;
- hb_hashmap_t<unsigned, hb_set_t *> *gpos_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_langsys;
//active features after removing redundant langsys and prune_features
hb_map_t *gsub_features;
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index 31ddb4f894..10c572c2f7 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -56,6 +56,7 @@
#include "hb-repacker.hh"
using OT::Layout::GSUB::GSUB;
+using OT::Layout::GPOS;
/**
* SECTION:hb-subset
@@ -78,6 +79,108 @@ using OT::Layout::GSUB::GSUB;
* retain glyph ids option and configure the subset to pass through the layout tables untouched.
*/
+/*
+ * The list of tables in the open type spec. Used to check for tables that may need handling
+ * if we are unable to list the tables in a face.
+ */
+static hb_tag_t known_tables[] {
+ HB_TAG ('a', 'v', 'a', 'r'),
+ HB_OT_TAG_BASE,
+ HB_OT_TAG_CBDT,
+ HB_OT_TAG_CBLC,
+ HB_OT_TAG_cff1,
+ HB_OT_TAG_cff2,
+ HB_OT_TAG_cmap,
+ HB_OT_TAG_COLR,
+ HB_OT_TAG_CPAL,
+ HB_TAG ('c', 'v', 'a', 'r'),
+ HB_TAG ('c', 'v', 't', ' '),
+ HB_TAG ('D', 'S', 'I', 'G'),
+ HB_TAG ('E', 'B', 'D', 'T'),
+ HB_TAG ('E', 'B', 'L', 'C'),
+ HB_TAG ('E', 'B', 'S', 'C'),
+ HB_TAG ('f', 'p', 'g', 'm'),
+ HB_TAG ('f', 'v', 'a', 'r'),
+ HB_TAG ('g', 'a', 's', 'p'),
+ HB_OT_TAG_GDEF,
+ HB_OT_TAG_glyf,
+ HB_OT_TAG_GPOS,
+ HB_OT_TAG_GSUB,
+ HB_OT_TAG_gvar,
+ HB_OT_TAG_hdmx,
+ HB_OT_TAG_head,
+ HB_OT_TAG_hhea,
+ HB_OT_TAG_hmtx,
+ HB_OT_TAG_HVAR,
+ HB_OT_TAG_JSTF,
+ HB_TAG ('k', 'e', 'r', 'n'),
+ HB_OT_TAG_loca,
+ HB_TAG ('L', 'T', 'S', 'H'),
+ HB_OT_TAG_MATH,
+ HB_OT_TAG_maxp,
+ HB_TAG ('M', 'E', 'R', 'G'),
+ HB_TAG ('m', 'e', 't', 'a'),
+ HB_TAG ('M', 'V', 'A', 'R'),
+ HB_TAG ('P', 'C', 'L', 'T'),
+ HB_OT_TAG_post,
+ HB_TAG ('p', 'r', 'e', 'p'),
+ HB_OT_TAG_sbix,
+ HB_TAG ('S', 'T', 'A', 'T'),
+ HB_TAG ('S', 'V', 'G', ' '),
+ HB_TAG ('V', 'D', 'M', 'X'),
+ HB_OT_TAG_vhea,
+ HB_OT_TAG_vmtx,
+ HB_OT_TAG_VORG,
+ HB_OT_TAG_VVAR,
+ HB_OT_TAG_name,
+ HB_OT_TAG_OS2
+};
+
+static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag)
+{
+ hb_blob_t* blob = hb_face_reference_table (face, tag);
+ bool result = (blob == hb_blob_get_empty ());
+ hb_blob_destroy (blob);
+ return result;
+}
+
+static unsigned int
+_get_table_tags (const hb_subset_plan_t* plan,
+ unsigned int start_offset,
+ unsigned int *table_count, /* IN/OUT */
+ hb_tag_t *table_tags /* OUT */)
+{
+ unsigned num_tables = hb_face_get_table_tags (plan->source, 0, nullptr, nullptr);
+ if (num_tables)
+ return hb_face_get_table_tags (plan->source, start_offset, table_count, table_tags);
+
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking each table type we can handle for existence instead.
+ auto it =
+ hb_concat (
+ + hb_array (known_tables)
+ | hb_filter ([&] (hb_tag_t tag) {
+ return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables->has (tag);
+ })
+ | hb_map ([] (hb_tag_t tag) -> hb_tag_t { return tag; }),
+
+ plan->no_subset_tables->iter ()
+ | hb_filter([&] (hb_tag_t tag) {
+ return !_table_is_empty (plan->source, tag);
+ }));
+
+ it += start_offset;
+
+ unsigned num_written = 0;
+ while (bool (it) && num_written < *table_count)
+ table_tags[num_written++] = *it++;
+
+ *table_count = num_written;
+ return num_written;
+}
+
+
static unsigned
_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
unsigned table_len,
@@ -224,9 +327,17 @@ _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
static bool
_is_table_present (hb_face_t *source, hb_tag_t tag)
{
+
+ if (!hb_face_get_table_tags (source, 0, nullptr, nullptr)) {
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking if the blob associated with tag is empty.
+ return !_table_is_empty (source, tag);
+ }
+
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ while (((void) hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
if (table_tags[i] == tag)
@@ -322,7 +433,7 @@ _subset_table (hb_subset_plan_t *plan,
#ifndef HB_NO_SUBSET_LAYOUT
case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf);
case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf);
- case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan, buf);
+ case HB_OT_TAG_GPOS: return _subset<const GPOS> (plan, buf);
case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf);
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
@@ -388,7 +499,8 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
hb_vector_t<char> buf;
buf.alloc (4096 - 16);
- while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
+
+ while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
@@ -400,7 +512,7 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
}
offset += num_tables;
}
-end:
+end:
return success ? hb_face_reference (plan->dest) : nullptr;
}
diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh
index 1a4c89c17f..9e76ca460b 100644
--- a/thirdparty/harfbuzz/src/hb-ucd-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh
@@ -13,7 +13,7 @@
#include "hb.hh"
static const hb_script_t
-_hb_ucd_sc_map[162] =
+_hb_ucd_sc_map[163] =
{
HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED,
HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC,
@@ -96,6 +96,7 @@ _hb_ucd_sc_map[162] =
HB_SCRIPT_YEZIDI, HB_SCRIPT_CYPRO_MINOAN,
HB_SCRIPT_OLD_UYGHUR, HB_SCRIPT_TANGSA,
HB_SCRIPT_TOTO, HB_SCRIPT_VITHKUQI,
+ HB_SCRIPT_MATH,
};
static const uint16_t
_hb_ucd_dm1_p0_map[825] =
diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc
index 83ead6398b..05f74b9237 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.cc
+++ b/thirdparty/harfbuzz/src/hb-unicode.cc
@@ -169,7 +169,7 @@ hb_unicode_funcs_get_default ()
#endif
/**
- * hb_unicode_funcs_create: (Xconstructor)
+ * hb_unicode_funcs_create:
* @parent: (nullable): Parent Unicode-functions structure
*
* Creates a new #hb_unicode_funcs_t structure of Unicode functions.
diff --git a/thirdparty/harfbuzz/src/hb-unicode.hh b/thirdparty/harfbuzz/src/hb-unicode.hh
index 4c28bb0cdf..39aaee5baa 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.hh
+++ b/thirdparty/harfbuzz/src/hb-unicode.hh
@@ -105,12 +105,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
unsigned int
modified_combining_class (hb_codepoint_t u)
{
- /* XXX This hack belongs to the USE shaper (for Tai Tham):
- * Reorder SAKOT to ensure it comes after any tone marks. */
+ /* Reorder SAKOT to ensure it comes after any tone marks. */
if (unlikely (u == 0x1A60u)) return 254;
-
- /* XXX This hack belongs to the Tibetan shaper:
- * Reorder PADMA to ensure it comes after any vowel marks. */
+ /* Reorder PADMA to ensure it comes after any vowel marks. */
if (unlikely (u == 0x0FC6u)) return 254;
/* Reorder TSA -PHRU to reorder before U+0F74 */
if (unlikely (u == 0x0F39u)) return 127;
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index ae707cde6c..f036a12226 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -47,20 +47,20 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 4
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 0
+#define HB_VERSION_MICRO 1
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "4.3.0"
+#define HB_VERSION_STRING "4.4.1"
/**
* HB_VERSION_ATLEAST:
diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh
index b9f5f71415..8ec638a2b4 100644
--- a/thirdparty/harfbuzz/src/hb.hh
+++ b/thirdparty/harfbuzz/src/hb.hh
@@ -29,7 +29,6 @@
#ifndef HB_HH
#define HB_HH
-
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
#ifdef _MSC_VER
#pragma warning( disable: 4068 ) /* Unknown pragma */
@@ -65,6 +64,7 @@
#pragma GCC diagnostic error "-Wbitwise-instead-of-logical"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
+#pragma GCC diagnostic error "-Wcomma"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic error "-Wembedded-directive"
#pragma GCC diagnostic error "-Wextra-semi-stmt"
@@ -183,7 +183,7 @@
#include <cassert>
#include <cfloat>
#include <climits>
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
# define _USE_MATH_DEFINES
#endif
#include <cmath>
@@ -470,6 +470,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
/* Headers we include for everyone. Keep topologically sorted by dependency.
* They express dependency amongst themselves, but no other file should include
* them directly.*/
+#include "hb-cplusplus.hh"
#include "hb-meta.hh"
#include "hb-mutex.hh"
#include "hb-number.hh"